1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.car.cluster; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.SystemApi; 22 import android.graphics.Rect; 23 import android.os.Bundle; 24 25 /** 26 * Helper class that represents activity state in the cluster and can be serialized / deserialized 27 * to/from bundle. 28 * 29 * @hide 30 */ 31 @SystemApi 32 public final class ClusterActivityState { 33 private static final String KEY_VISIBLE = "android.car:activityState.visible"; 34 private static final String KEY_UNOBSCURED_BOUNDS = "android.car:activityState.unobscured"; 35 private static final String KEY_EXTRAS = "android.car:activityState.extras"; 36 37 private boolean mVisible = true; 38 private Rect mUnobscuredBounds; 39 private Bundle mExtras; 40 41 /** 42 * Returns true if the cluster is currently able to display content, or false if the content 43 * area of the cluster is hidden. 44 */ isVisible()45 public boolean isVisible() { 46 return mVisible; 47 } 48 49 /** 50 * Get a rectangle inside the cluster content area that is not covered by any decorations. 51 * Activities designed to display content in the instrument cluster can use this information to 52 * determine where to display user-relevant content, while using the rest of the window for 53 * content bleeding. For example, a navigation activity could decide to display current road 54 * inside this rectangle, while drawing additional map background outside this area. 55 * <p> 56 * All values of this {@link Rect} represent absolute coordinates inside the activity canvas. 57 */ getUnobscuredBounds()58 @Nullable public Rect getUnobscuredBounds() { 59 return mUnobscuredBounds; 60 } 61 62 /** 63 * Get any custom extras that were set on this activity state. 64 */ getExtras()65 @Nullable public Bundle getExtras() { 66 return mExtras; 67 } 68 69 /** 70 * Sets whether the cluster is currently able to display content, or false if content area of 71 * the cluster is hidden. 72 * 73 * @return this instance for chaining. 74 */ setVisible(boolean visible)75 @NonNull public ClusterActivityState setVisible(boolean visible) { 76 mVisible = visible; 77 return this; 78 } 79 80 /** 81 * Sets a rectangle inside that cluster content area that is not covered by any decorations. 82 * Activities designed to display content in the cluster can use this to determine where to 83 * display user-relevant content, while using the rest of the window for content bleeding. 84 * 85 * @param unobscuredBounds a {@link Rect} describing the area inside the activity canvas that is 86 * not covered by any decorations. All values of this {@link Rect} 87 * represent absolute coordinates inside the activity canvas. 88 * @return this instance for chaining. 89 */ setUnobscuredBounds(@onNull Rect unobscuredBounds)90 @NonNull public ClusterActivityState setUnobscuredBounds(@NonNull Rect unobscuredBounds) { 91 mUnobscuredBounds = unobscuredBounds; 92 return this; 93 } 94 95 /** 96 * Set any custom extras to be included with the activity state. 97 * 98 * @return this instance for chaining. 99 */ setExtras(@onNull Bundle bundle)100 @NonNull public ClusterActivityState setExtras(@NonNull Bundle bundle) { 101 mExtras = bundle; 102 return this; 103 } 104 105 /** Use factory methods instead. */ ClusterActivityState()106 private ClusterActivityState() {} 107 108 /** 109 * Creates a {@link ClusterActivityState} with the given visibility and unobscured bounds (see 110 * {@link #setVisible(boolean)} and {@link #setUnobscuredBounds(Rect)} for more details) 111 */ create( boolean visible, @NonNull Rect unobscuredBounds)112 @NonNull public static ClusterActivityState create( 113 boolean visible, @NonNull Rect unobscuredBounds) { 114 return new ClusterActivityState() 115 .setVisible(visible) 116 .setUnobscuredBounds(unobscuredBounds); 117 } 118 119 /** 120 * Reconstructs a {@link ClusterActivityState} from a {@link Bundle} 121 */ fromBundle(@onNull Bundle bundle)122 @NonNull public static ClusterActivityState fromBundle(@NonNull Bundle bundle) { 123 return new ClusterActivityState() 124 .setVisible(bundle.getBoolean(KEY_VISIBLE, true)) 125 .setUnobscuredBounds((Rect) bundle.getParcelable(KEY_UNOBSCURED_BOUNDS)) 126 .setExtras(bundle.getBundle(KEY_EXTRAS)); 127 } 128 129 /** 130 * Returns a {@link Bundle} representation of this instance. This bundle can then be 131 * deserialized using {@link #fromBundle(Bundle)}. 132 */ toBundle()133 @NonNull public Bundle toBundle() { 134 Bundle b = new Bundle(); 135 b.putBoolean(KEY_VISIBLE, mVisible); 136 b.putParcelable(KEY_UNOBSCURED_BOUNDS, mUnobscuredBounds); 137 b.putBundle(KEY_EXTRAS, mExtras); 138 return b; 139 } 140 141 @Override toString()142 public String toString() { 143 return this.getClass().getSimpleName() + " {" 144 + "visible: " + mVisible + ", " 145 + "unobscuredBounds: " + mUnobscuredBounds + ", " 146 + "extras: " + mExtras 147 + " }"; 148 } 149 } 150