1 /*
2  * Copyright (C) 2021 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.hardware.devicestate;
18 
19 import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
20 import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
21 
22 import android.annotation.FlaggedApi;
23 import android.annotation.IntDef;
24 import android.annotation.IntRange;
25 import android.annotation.NonNull;
26 import android.annotation.SystemApi;
27 import android.annotation.TestApi;
28 import android.os.Parcel;
29 import android.os.Parcelable;
30 import android.util.ArraySet;
31 
32 import java.lang.annotation.ElementType;
33 import java.lang.annotation.Retention;
34 import java.lang.annotation.RetentionPolicy;
35 import java.lang.annotation.Target;
36 import java.util.Collections;
37 import java.util.Objects;
38 import java.util.Set;
39 
40 /**
41  * A state of the device managed by {@link DeviceStateManager}.
42  * <p>
43  * Device state is an abstract concept that allows mapping the current state of the device to the
44  * state of the system. This is useful for variable-state devices, like foldable or rollable
45  * devices, that can be configured by users into differing hardware states, which each may have a
46  * different expected use case.
47  *
48  * @hide
49  * @see DeviceStateManager
50  */
51 @SystemApi
52 @FlaggedApi(android.hardware.devicestate.feature.flags.Flags.FLAG_DEVICE_STATE_PROPERTY_API)
53 public final class DeviceState {
54     /**
55      * Property that indicates that a fold-in style foldable device is currently in a fully closed
56      * configuration.
57      */
58     public static final int PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED = 1;
59 
60     /**
61      * Property that indicates that a fold-in style foldable device is currently in a half-opened
62      * configuration. This signifies that the device's hinge is positioned somewhere around 90
63      * degrees. Checking for display configuration properties as well can provide information
64      * on which display is currently active.
65      */
66     public static final int PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN = 2;
67 
68     /**
69      * Property that indicates that a fold-in style foldable device is currently in a fully open
70      * configuration.
71      */
72     public static final int PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN = 3;
73 
74     /**
75      * Property that indicates override requests should be cancelled when the device is physically
76      * put into this state.
77      * @hide
78      */
79     public static final int PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS = 4;
80 
81     /**
82      * This property indicates that the corresponding state should be automatically canceled when
83      * the requesting app is no longer on top. The app is considered not on top when (1) the top
84      * activity in the system is from a different app, (2) the device is in sleep mode, or
85      * (3) the keyguard shows up.
86      * @hide
87      */
88     public static final int PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP = 5;
89 
90     /**
91      * This property indicates that the corresponding state should be disabled when the device is
92      * overheating and reaching the critical status.
93      * @hide
94      */
95     public static final int PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL = 6;
96 
97     /**
98      * This property indicates that the corresponding state should be disabled when power save mode
99      * is enabled.
100      * @hide
101      */
102     public static final int PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE = 7;
103 
104     /**
105      * This property denotes that this state is available for applications to request and the system
106      * server should deny any request that comes from a process that does not hold the
107      * CONTROL_DEVICE_STATE permission if it is requesting a state that does not have this property
108      * on it.
109      * @hide
110      */
111     @TestApi
112     public static final int PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST = 8;
113 
114     /**
115      * Property that indicates this device state is inaccessible for applications to be made
116      * visible to the user. This could be a device-state where the {@link Display#DEFAULT_DISPLAY}
117      * is not enabled.
118      * @hide
119      */
120     public static final int PROPERTY_APP_INACCESSIBLE = 9;
121 
122     /**
123      * This property indidcates that this state can only be entered through emulation and has no
124      * physical configuration to match.
125      */
126     public static final int PROPERTY_EMULATED_ONLY = 10;
127 
128     /**
129      * Property that indicates that the outer display area of a foldable device is currently the
130      * primary display area.
131      *
132      * Note: This does not necessarily mean that the outer display area is the
133      * {@link Display#DEFAULT_DISPLAY}.
134      */
135     public static final int PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY = 11;
136 
137     /**
138      * Property that indicates that the inner display area of a foldable device is currently the
139      * primary display area.
140      *
141      * Note: This does not necessarily mean that the inner display area is the
142      * {@link Display#DEFAULT_DISPLAY}.
143      */
144     public static final int PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY = 12;
145 
146     /**
147      * Property that indicates that this device state will attempt to trigger the device to go to
148      * sleep.
149      */
150     public static final int PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP = 13;
151 
152     /**
153      * Property that indicates that this device state will attempt to trigger the device to wake up.
154      */
155     public static final int PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE = 14;
156 
157     /**
158      * Property that indicates that an external display has been connected to the device. Specifics
159      * around display mode or properties around the display should be gathered through
160      * {@link android.hardware.display.DisplayManager}
161      */
162     public static final int PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY = 15;
163     /**
164      * Property that indicates that this state corresponds to the device state for rear display
165      * mode. This means that the active display is facing the same direction as the rear camera.
166      */
167     public static final int PROPERTY_FEATURE_REAR_DISPLAY = 16;
168 
169     /**
170      * Property that indicates that this state corresponds to the device state where both displays
171      * on a foldable are active, with the internal display being the default display.
172      */
173     public static final int PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT = 17;
174 
175     /** @hide */
176     @IntDef(prefix = {"PROPERTY_"}, flag = false, value = {
177             PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED,
178             PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN,
179             PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN,
180             PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS,
181             PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP,
182             PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL,
183             PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE,
184             PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST,
185             PROPERTY_APP_INACCESSIBLE,
186             PROPERTY_EMULATED_ONLY,
187             PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY,
188             PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY,
189             PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP,
190             PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE,
191             PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY,
192             PROPERTY_FEATURE_REAR_DISPLAY,
193             PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT
194     })
195     @Retention(RetentionPolicy.SOURCE)
196     @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
197     public @interface DeviceStateProperties {}
198 
199     /** @hide */
200     @IntDef(prefix = {"PROPERTY_"}, flag = false, value = {
201             PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED,
202             PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN,
203             PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN
204     })
205     @Retention(RetentionPolicy.SOURCE)
206     @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
207     public @interface PhysicalDeviceStateProperties {}
208 
209     /** @hide */
210     @IntDef(prefix = {"PROPERTY_"}, flag = false, value = {
211             PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS,
212             PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP,
213             PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL,
214             PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE,
215             PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST,
216             PROPERTY_APP_INACCESSIBLE,
217             PROPERTY_EMULATED_ONLY,
218             PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY,
219             PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY,
220             PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP,
221             PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE,
222             PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY,
223             PROPERTY_FEATURE_REAR_DISPLAY,
224             PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT
225     })
226     @Retention(RetentionPolicy.SOURCE)
227     @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
228     public @interface SystemDeviceStateProperties {}
229 
230     @NonNull
231     private final DeviceState.Configuration mDeviceStateConfiguration;
232 
233     /** @hide */
234     @TestApi
DeviceState(@onNull DeviceState.Configuration deviceStateConfiguration)235     public DeviceState(@NonNull DeviceState.Configuration deviceStateConfiguration) {
236         Objects.requireNonNull(deviceStateConfiguration, "Device StateConfiguration is null");
237         mDeviceStateConfiguration = deviceStateConfiguration;
238     }
239 
240     /** Returns the unique identifier for the device state. */
241     @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER)
getIdentifier()242     public int getIdentifier() {
243         return mDeviceStateConfiguration.getIdentifier();
244     }
245 
246     /** Returns a string description of the device state. */
247     @NonNull
getName()248     public String getName() {
249         return mDeviceStateConfiguration.getName();
250     }
251 
252     @Override
toString()253     public String toString() {
254         return "DeviceState{" + "identifier=" + mDeviceStateConfiguration.getIdentifier()
255                 + ", name='" + mDeviceStateConfiguration.getName() + '\''
256                 + ", app_accessible=" + !mDeviceStateConfiguration.getSystemProperties().contains(
257                 PROPERTY_APP_INACCESSIBLE)
258                 + ", cancel_when_requester_not_on_top="
259                 + mDeviceStateConfiguration.getSystemProperties().contains(
260                 PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)
261                 + "}";
262     }
263 
264     @Override
equals(Object o)265     public boolean equals(Object o) {
266         if (this == o) return true;
267         if (o == null || getClass() != o.getClass()) return false;
268         DeviceState that = (DeviceState) o;
269         return Objects.equals(mDeviceStateConfiguration, that.mDeviceStateConfiguration);
270     }
271 
272     @Override
hashCode()273     public int hashCode() {
274         return Objects.hash(mDeviceStateConfiguration);
275     }
276 
277     /**
278      * Checks if a specific property is set on this state
279      */
hasProperty(@eviceStateProperties int propertyToCheckFor)280     public boolean hasProperty(@DeviceStateProperties int propertyToCheckFor) {
281         return mDeviceStateConfiguration.mSystemProperties.contains(propertyToCheckFor)
282                 || mDeviceStateConfiguration.mPhysicalProperties.contains(propertyToCheckFor);
283     }
284 
285     /**
286      * Checks if a list of properties are all set on this state
287      */
hasProperties(@onNull @eviceStateProperties int... properties)288     public boolean hasProperties(@NonNull @DeviceStateProperties int... properties) {
289         for (int i = 0; i < properties.length; i++) {
290             if (!hasProperty(properties[i])) {
291                 return false;
292             }
293         }
294         return true;
295     }
296 
297     /**
298      * Returns the underlying {@link DeviceState.Configuration} object used to model the
299      * device state.
300      * @hide
301      */
getConfiguration()302     public Configuration getConfiguration() {
303         return mDeviceStateConfiguration;
304     }
305 
306     /**
307      * Detailed description of a {@link DeviceState} that includes separated sets of
308      * {@link DeviceStateProperties} for properties that correspond to the state of the system when
309      * the device is in this state, as well as physical properties that describe this state.
310      *
311      * Instantiation of this class should only be done by the system server, and clients of
312      * {@link DeviceStateManager} will receive {@link DeviceState} objects.
313      *
314      * @see DeviceStateManager
315      * @hide
316      */
317     @TestApi
318     public static final class Configuration implements Parcelable {
319         /** Unique identifier for the device state. */
320         @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to = MAXIMUM_DEVICE_STATE_IDENTIFIER)
321         private final int mIdentifier;
322 
323         /** String description of the device state. */
324         @NonNull
325         private final String mName;
326 
327         /** {@link ArraySet} of system properties that apply to this state. */
328         @NonNull
329         private final ArraySet<@SystemDeviceStateProperties Integer> mSystemProperties;
330 
331         /** {@link ArraySet} of physical device properties that apply to this state. */
332         @NonNull
333         private final ArraySet<@PhysicalDeviceStateProperties Integer> mPhysicalProperties;
334 
Configuration(int identifier, @NonNull String name, @NonNull ArraySet<@SystemDeviceStateProperties Integer> systemProperties, @NonNull ArraySet<@PhysicalDeviceStateProperties Integer> physicalProperties)335         private Configuration(int identifier, @NonNull String name,
336                 @NonNull ArraySet<@SystemDeviceStateProperties Integer> systemProperties,
337                 @NonNull ArraySet<@PhysicalDeviceStateProperties Integer> physicalProperties) {
338             mIdentifier = identifier;
339             mName = name;
340             mSystemProperties = systemProperties;
341             mPhysicalProperties = physicalProperties;
342         }
343 
344         /** Returns the unique identifier for the device state. */
getIdentifier()345         public int getIdentifier() {
346             return mIdentifier;
347         }
348 
349         /** Returns a string description of the device state. */
350         @NonNull
getName()351         public String getName() {
352             return mName;
353         }
354 
355         /** Returns the {@link Set} of system properties that apply to this state. */
356         @NonNull
getSystemProperties()357         public Set<@SystemDeviceStateProperties Integer> getSystemProperties() {
358             return mSystemProperties;
359         }
360 
361         /** Returns the {@link Set} of physical device properties that apply to this state. */
362         @NonNull
getPhysicalProperties()363         public Set<@DeviceStateProperties Integer> getPhysicalProperties() {
364             return mPhysicalProperties;
365         }
366 
367         @Override
toString()368         public String toString() {
369             return "DeviceState{" + "identifier=" + mIdentifier
370                     + ", name='" + mName + '\''
371                     + ", app_accessible=" + mSystemProperties.contains(PROPERTY_APP_INACCESSIBLE)
372                     + ", cancel_when_requester_not_on_top="
373                     + mSystemProperties.contains(PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)
374                     + "}";
375         }
376 
377         @Override
equals(Object o)378         public boolean equals(Object o) {
379             if (this == o) return true;
380             if (o == null || getClass() != o.getClass()) return false;
381             DeviceState.Configuration that = (DeviceState.Configuration) o;
382             return mIdentifier == that.mIdentifier
383                     && Objects.equals(mName, that.mName)
384                     && Objects.equals(mSystemProperties, that.mSystemProperties)
385                     && Objects.equals(mPhysicalProperties, that.mPhysicalProperties);
386         }
387 
388         @Override
hashCode()389         public int hashCode() {
390             return Objects.hash(mIdentifier, mName, mSystemProperties, mPhysicalProperties);
391         }
392 
393         @Override
describeContents()394         public int describeContents() {
395             return 0;
396         }
397 
398         @Override
writeToParcel(@onNull Parcel dest, int flags)399         public void writeToParcel(@NonNull Parcel dest, int flags) {
400             dest.writeInt(mIdentifier);
401             dest.writeString8(mName);
402             dest.writeArraySet(mSystemProperties);
403             dest.writeArraySet(mPhysicalProperties);
404         }
405 
406         @NonNull
407         public static final Creator<DeviceState.Configuration> CREATOR = new Creator<>() {
408             @Override
409             public DeviceState.Configuration createFromParcel(Parcel source) {
410                 int identifier = source.readInt();
411                 String name = source.readString8();
412                 ArraySet<@SystemDeviceStateProperties Integer> systemProperties =
413                         (ArraySet<Integer>) source.readArraySet(null /* classLoader */);
414                 ArraySet<@PhysicalDeviceStateProperties Integer> physicalProperties =
415                         (ArraySet<Integer>) source.readArraySet(null /* classLoader */);
416 
417                 return new DeviceState.Configuration(identifier, name, systemProperties,
418                         physicalProperties);
419             }
420 
421             @Override
422             public DeviceState.Configuration[] newArray(int size) {
423                 return new DeviceState.Configuration[size];
424             }
425         };
426 
427         /** @hide */
428         @TestApi
429         public static final class Builder {
430             private final int mIdentifier;
431             @NonNull
432             private final String mName;
433             @NonNull
434             private Set<@SystemDeviceStateProperties Integer> mSystemProperties =
435                     Collections.emptySet();
436             @NonNull
437             private Set<@PhysicalDeviceStateProperties Integer> mPhysicalProperties =
438                     Collections.emptySet();
439 
Builder(int identifier, @NonNull String name)440             public Builder(int identifier, @NonNull String name) {
441                 mIdentifier = identifier;
442                 mName = name;
443             }
444 
445             /** Sets the system properties for this {@link DeviceState.Configuration.Builder} */
446             @NonNull
setSystemProperties( @onNull Set<@SystemDeviceStateProperties Integer> systemProperties)447             public Builder setSystemProperties(
448                     @NonNull Set<@SystemDeviceStateProperties Integer> systemProperties) {
449                 mSystemProperties = systemProperties;
450                 return this;
451             }
452 
453             /** Sets the system properties for this {@link DeviceState.Configuration.Builder} */
454             @NonNull
setPhysicalProperties( @onNull Set<@PhysicalDeviceStateProperties Integer> physicalProperties)455             public Builder setPhysicalProperties(
456                     @NonNull Set<@PhysicalDeviceStateProperties Integer> physicalProperties) {
457                 mPhysicalProperties = physicalProperties;
458                 return this;
459             }
460 
461             /**
462              * Returns a new {@link DeviceState.Configuration} whose values match the values set on
463              * the builder.
464              */
465             @NonNull
build()466             public DeviceState.Configuration build() {
467                 return new DeviceState.Configuration(mIdentifier, mName,
468                         new ArraySet<>(mSystemProperties), new ArraySet<>(mPhysicalProperties));
469             }
470         }
471     }
472 }
473