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.Nullable;
20 import android.graphics.Rect;
21 import android.os.Bundle;
22 
23 /**
24  * Helper class that represents activity state in the cluster and can be serialized / deserialized
25  * to/from bundle.
26  *
27  * @hide
28  */
29 public class ClusterActivityState {
30     private static final String KEY_VISIBLE = "android.car:activityState.visible";
31     private static final String KEY_UNOBSCURED_BOUNDS = "android.car:activityState.unobscured";
32     private static final String KEY_EXTRAS = "android.car:activityState.extras";
33 
34     private boolean mVisible = true;
35     private Rect mUnobscuredBounds;
36     private Bundle mExtras;
37 
38     /**
39      * Returns true if the cluster is currently able to display content, or false if the content
40      * area of the cluster is hidden.
41      */
isVisible()42     public boolean isVisible() {
43         return mVisible;
44     }
45 
46     /**
47      * Get a rectangle inside the cluster content area that is not covered by any decorations.
48      * Activities designed to display content in the instrument cluster can use this information to
49      * determine where to display user-relevant content, while using the rest of the window for
50      * content bleeding. For example, a navigation activity could decide to display current road
51      * inside this rectangle, while drawing additional map background outside this area.
52      * <p>
53      * All values of this {@link Rect} represent absolute coordinates inside the activity canvas.
54      */
getUnobscuredBounds()55     @Nullable public Rect getUnobscuredBounds() {
56         return mUnobscuredBounds;
57     }
58 
59     /**
60      * Get any custom extras that were set on this activity state.
61      */
getExtras()62     @Nullable public Bundle getExtras() {
63         return mExtras;
64     }
65 
66     /**
67      * Sets whether the cluster is currently able to display content, or false if content area of
68      * the cluster is hidden.
69      *
70      * @return this instance for chaining.
71      */
setVisible(boolean visible)72     public ClusterActivityState setVisible(boolean visible) {
73         mVisible = visible;
74         return this;
75     }
76 
77     /**
78      * Sets a rectangle inside that cluster content area that is not covered by any decorations.
79      * Activities designed to display content in the cluster can use this to determine where to
80      * display user-relevant content, while using the rest of the window for content bleeding.
81      *
82      * @param unobscuredBounds a {@link Rect} describing the area inside the activity canvas that is
83      *                         not covered by any decorations. All values of this {@link Rect}
84      *                         represent absolute coordinates inside the activity canvas.
85      * @return this instance for chaining.
86      */
setUnobscuredBounds(Rect unobscuredBounds)87     public ClusterActivityState setUnobscuredBounds(Rect unobscuredBounds) {
88         mUnobscuredBounds = unobscuredBounds;
89         return this;
90     }
91 
92     /**
93      * Set any custom extras to be included with the activity state.
94      *
95      * @return this instance for chaining.
96      */
setExtras(Bundle bundle)97     public ClusterActivityState setExtras(Bundle bundle) {
98         mExtras = bundle;
99         return this;
100     }
101 
102     /** Use factory methods instead. */
ClusterActivityState()103     private ClusterActivityState() {}
104 
105     /**
106      * Creates a {@link ClusterActivityState} with the given visibility and unobscured bounds (see
107      * {@link #setVisible(boolean)} and {@link #setUnobscuredBounds(Rect)} for more details)
108      */
create(boolean visible, Rect unobscuredBounds)109     public static ClusterActivityState create(boolean visible, Rect unobscuredBounds) {
110         return new ClusterActivityState()
111                 .setVisible(visible)
112                 .setUnobscuredBounds(unobscuredBounds);
113     }
114 
115     /**
116      * Reconstructs a {@link ClusterActivityState} from a {@link Bundle}
117      */
fromBundle(Bundle bundle)118     public static ClusterActivityState fromBundle(Bundle bundle) {
119         return new ClusterActivityState()
120                 .setVisible(bundle.getBoolean(KEY_VISIBLE, true))
121                 .setUnobscuredBounds((Rect) bundle.getParcelable(KEY_UNOBSCURED_BOUNDS))
122                 .setExtras(bundle.getBundle(KEY_EXTRAS));
123     }
124 
125     /**
126      * Returns a {@link Bundle} representation of this instance. This bundle can then be
127      * deserialized using {@link #fromBundle(Bundle)}.
128      */
toBundle()129     public Bundle toBundle() {
130         Bundle b = new Bundle();
131         b.putBoolean(KEY_VISIBLE, mVisible);
132         b.putParcelable(KEY_UNOBSCURED_BOUNDS, mUnobscuredBounds);
133         b.putBundle(KEY_EXTRAS, mExtras);
134         return b;
135     }
136 
137     @Override
toString()138     public String toString() {
139         return this.getClass().getSimpleName() + " {"
140                 + "visible: " + mVisible + ", "
141                 + "unobscuredBounds: " + mUnobscuredBounds + ", "
142                 + "extras: " + mExtras
143                 + " }";
144     }
145 }
146