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