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