1 /* 2 * Copyright (C) 2020 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.user; 18 19 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.BOILERPLATE_CODE; 20 21 import android.annotation.IntDef; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.SystemApi; 25 import android.os.Parcelable; 26 import android.os.UserManager; 27 28 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport; 29 import com.android.car.internal.util.DataClass; 30 31 import java.lang.annotation.Retention; 32 import java.lang.annotation.RetentionPolicy; 33 34 /** 35 * User switch results. 36 * 37 * @hide 38 */ 39 @DataClass( 40 genToString = true, 41 genHiddenConstructor = true, 42 genHiddenConstDefs = true) 43 @SystemApi 44 public final class UserSwitchResult implements Parcelable, OperationResult { 45 46 /** 47 * When user switch is successful for both HAL and Android. 48 */ 49 @Status 50 public static final int STATUS_SUCCESSFUL = CommonResults.STATUS_SUCCESSFUL; 51 52 /** 53 * When user switch is only successful for Hal but not for Android. Hal user switch rollover 54 * message have been sent. 55 */ 56 @Status 57 public static final int STATUS_ANDROID_FAILURE = CommonResults.STATUS_ANDROID_FAILURE; 58 59 /** 60 * When user switch fails for HAL. User switch for Android is not called. 61 */ 62 @Status 63 public static final int STATUS_HAL_FAILURE = CommonResults.STATUS_HAL_FAILURE; 64 65 /** 66 * When user switch fails for HAL for some internal error. User switch for Android is not 67 * called. 68 */ 69 @Status 70 public static final int STATUS_HAL_INTERNAL_FAILURE = CommonResults.STATUS_HAL_INTERNAL_FAILURE; 71 72 /** 73 * When given parameters or environment states are invalid for switching user. HAL or Android 74 * user switch is not requested. 75 */ 76 @Status 77 public static final int STATUS_INVALID_REQUEST = CommonResults.STATUS_INVALID_REQUEST; 78 79 /** 80 * When user switch fails because of driving safety UX restrictions. 81 */ 82 @Status 83 public static final int STATUS_UX_RESTRICTION_FAILURE = 84 CommonResults.STATUS_UX_RESTRICTION_FAILURE; 85 86 /** 87 * When target user is same as current user. 88 */ 89 @Status 90 public static final int STATUS_OK_USER_ALREADY_IN_FOREGROUND = 91 CommonResults.LAST_COMMON_STATUS + 1; 92 93 /** 94 * When another user switch request for the same target user is in process. 95 */ 96 @Status 97 public static final int STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO = 98 CommonResults.LAST_COMMON_STATUS + 2; 99 100 /** 101 * When another user switch request for a new different target user is received. Previous 102 * request is abandoned. 103 */ 104 @Status 105 public static final int STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST = 106 CommonResults.LAST_COMMON_STATUS + 3; 107 108 /** 109 * When switching users is currently not allowed for the user this process is running under. 110 */ 111 @Status 112 public static final int STATUS_NOT_SWITCHABLE = 113 CommonResults.LAST_COMMON_STATUS + 4; 114 115 /** 116 * When logout was called but the current user was not switched by a device admin. 117 */ 118 @Status 119 public static final int STATUS_NOT_LOGGED_IN = 120 CommonResults.LAST_COMMON_STATUS + 5; 121 122 /** 123 * Gets the user switch result status. 124 * 125 * @return either {@link UserSwitchResult#STATUS_SUCCESSFUL}, 126 * {@link UserSwitchResult#STATUS_ANDROID_FAILURE}, 127 * {@link UserSwitchResult#STATUS_HAL_FAILURE}, 128 * {@link UserSwitchResult#STATUS_HAL_INTERNAL_FAILURE}, 129 * {@link UserSwitchResult#STATUS_INVALID_REQUEST}, 130 * {@link UserSwitchResult#STATUS_UX_RESTRICTION_FAILURE}, 131 * {@link UserSwitchResult#STATUS_OK_USER_ALREADY_IN_FOREGROUND}, 132 * {@link UserSwitchResult#STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO}, 133 * {@link UserSwitchResult#STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST}, 134 * {@link UserSwitchResult#STATUS_NOT_SWITCHABLE}, or 135 * {@link UserSwitchResult#STATUS_NOT_LOGGED_IN}. 136 */ 137 private final @Status int mStatus; 138 139 // TODO(b/214443810): codegen generates call to writeInteger() / readInteger(), we need to 140 // manually change to writeInt() / readInt() 141 /** 142 * Gets the failure status returned by {@link UserManager} when the {@link #getStatus() status} 143 * is {@link #STATUS_ANDROID_FAILURE}. 144 * 145 * @return {@code USER_OPERATION_ERROR_} constants defined by {@link UserManager}, or 146 * {@code null} when the {@link #getStatus() status} is not {@link #STATUS_ANDROID_FAILURE}. 147 */ 148 @Nullable 149 private final Integer mAndroidFailureStatus; 150 151 /** 152 * Gets the error message, if any. 153 */ 154 @Nullable 155 private final String mErrorMessage; 156 157 @Override isSuccess()158 public boolean isSuccess() { 159 return mStatus == STATUS_SUCCESSFUL || mStatus == STATUS_OK_USER_ALREADY_IN_FOREGROUND; 160 } 161 162 /** @hide */ UserSwitchResult(@tatus int status, @Nullable String errorMessage)163 public UserSwitchResult(@Status int status, @Nullable String errorMessage) { 164 this(status, /* androidFailureStatus= */ null, errorMessage); 165 } 166 167 // NOTE: codegen generates this method, but without @ExcludeFromCodeCoverageGeneratedReport 168 @Override 169 @ExcludeFromCodeCoverageGeneratedReport(reason = BOILERPLATE_CODE) describeContents()170 public int describeContents() { 171 return 0; 172 } 173 174 175 176 // Code below generated by codegen v1.0.23. 177 // 178 // DO NOT MODIFY! 179 // CHECKSTYLE:OFF Generated code 180 // 181 // To regenerate run: 182 // $ codegen $ANDROID_BUILD_TOP/packages/services/Car/car-lib/src/android/car/user/UserSwitchResult.java 183 // Added AddedInOrBefore or ApiRequirement Annotation manually 184 // 185 // To exclude the generated code from IntelliJ auto-formatting enable (one-time): 186 // Settings > Editor > Code Style > Formatter Control 187 //@formatter:off 188 189 190 /** @hide */ 191 @IntDef(prefix = "STATUS_", value = { 192 STATUS_SUCCESSFUL, 193 STATUS_ANDROID_FAILURE, 194 STATUS_HAL_FAILURE, 195 STATUS_HAL_INTERNAL_FAILURE, 196 STATUS_INVALID_REQUEST, 197 STATUS_UX_RESTRICTION_FAILURE, 198 STATUS_OK_USER_ALREADY_IN_FOREGROUND, 199 STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO, 200 STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST, 201 STATUS_NOT_SWITCHABLE, 202 STATUS_NOT_LOGGED_IN 203 }) 204 @Retention(RetentionPolicy.SOURCE) 205 @DataClass.Generated.Member 206 public @interface Status {} 207 208 @DataClass.Generated.Member 209 @ExcludeFromCodeCoverageGeneratedReport(reason = BOILERPLATE_CODE) 210 @NonNull statusToString(@tatus int value)211 public static String statusToString(@Status int value) { 212 switch (value) { 213 case STATUS_SUCCESSFUL: 214 return "STATUS_SUCCESSFUL"; 215 case STATUS_ANDROID_FAILURE: 216 return "STATUS_ANDROID_FAILURE"; 217 case STATUS_HAL_FAILURE: 218 return "STATUS_HAL_FAILURE"; 219 case STATUS_HAL_INTERNAL_FAILURE: 220 return "STATUS_HAL_INTERNAL_FAILURE"; 221 case STATUS_INVALID_REQUEST: 222 return "STATUS_INVALID_REQUEST"; 223 case STATUS_UX_RESTRICTION_FAILURE: 224 return "STATUS_UX_RESTRICTION_FAILURE"; 225 case STATUS_OK_USER_ALREADY_IN_FOREGROUND: 226 return "STATUS_OK_USER_ALREADY_IN_FOREGROUND"; 227 case STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO: 228 return "STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO"; 229 case STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST: 230 return "STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST"; 231 case STATUS_NOT_SWITCHABLE: 232 return "STATUS_NOT_SWITCHABLE"; 233 case STATUS_NOT_LOGGED_IN: 234 return "STATUS_NOT_LOGGED_IN"; 235 default: return Integer.toHexString(value); 236 } 237 } 238 239 /** 240 * Creates a new UserSwitchResult. 241 * 242 * @param status 243 * Gets the user switch result status. 244 * 245 * @return either {@link UserSwitchResult#STATUS_SUCCESSFUL}, 246 * {@link UserSwitchResult#STATUS_ANDROID_FAILURE}, 247 * {@link UserSwitchResult#STATUS_HAL_FAILURE}, 248 * {@link UserSwitchResult#STATUS_HAL_INTERNAL_FAILURE}, 249 * {@link UserSwitchResult#STATUS_INVALID_REQUEST}, 250 * {@link UserSwitchResult#STATUS_UX_RESTRICTION_FAILURE}, 251 * {@link UserSwitchResult#STATUS_OK_USER_ALREADY_IN_FOREGROUND}, 252 * {@link UserSwitchResult#STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO}, 253 * {@link UserSwitchResult#STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST}, 254 * {@link UserSwitchResult#STATUS_NOT_SWITCHABLE}, or 255 * {@link UserSwitchResult#STATUS_NOT_LOGGED_IN}. 256 * @param androidFailureStatus 257 * Gets the failure status returned by {@link UserManager} when the {@link #getStatus() status} 258 * is {@link #STATUS_ANDROID_FAILURE}. 259 * 260 * @return {@code USER_OPERATION_ERROR_} constants defined by {@link UserManager}, or 261 * {@code null} when the {@link #getStatus() status} is not {@link #STATUS_ANDROID_FAILURE}. 262 * @param errorMessage 263 * Gets the error message, if any. 264 * @hide 265 */ 266 @DataClass.Generated.Member UserSwitchResult( @tatus int status, @Nullable Integer androidFailureStatus, @Nullable String errorMessage)267 public UserSwitchResult( 268 @Status int status, 269 @Nullable Integer androidFailureStatus, 270 @Nullable String errorMessage) { 271 this.mStatus = status; 272 273 if (!(mStatus == STATUS_SUCCESSFUL) 274 && !(mStatus == STATUS_ANDROID_FAILURE) 275 && !(mStatus == STATUS_HAL_FAILURE) 276 && !(mStatus == STATUS_HAL_INTERNAL_FAILURE) 277 && !(mStatus == STATUS_INVALID_REQUEST) 278 && !(mStatus == STATUS_UX_RESTRICTION_FAILURE) 279 && !(mStatus == STATUS_OK_USER_ALREADY_IN_FOREGROUND) 280 && !(mStatus == STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO) 281 && !(mStatus == STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST) 282 && !(mStatus == STATUS_NOT_SWITCHABLE) 283 && !(mStatus == STATUS_NOT_LOGGED_IN)) { 284 throw new java.lang.IllegalArgumentException( 285 "status was " + mStatus + " but must be one of: " 286 + "STATUS_SUCCESSFUL(" + STATUS_SUCCESSFUL + "), " 287 + "STATUS_ANDROID_FAILURE(" + STATUS_ANDROID_FAILURE + "), " 288 + "STATUS_HAL_FAILURE(" + STATUS_HAL_FAILURE + "), " 289 + "STATUS_HAL_INTERNAL_FAILURE(" + STATUS_HAL_INTERNAL_FAILURE + "), " 290 + "STATUS_INVALID_REQUEST(" + STATUS_INVALID_REQUEST + "), " 291 + "STATUS_UX_RESTRICTION_FAILURE(" + STATUS_UX_RESTRICTION_FAILURE + "), " 292 + "STATUS_OK_USER_ALREADY_IN_FOREGROUND(" + STATUS_OK_USER_ALREADY_IN_FOREGROUND + "), " 293 + "STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO(" + STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO + "), " 294 + "STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST(" + STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST + "), " 295 + "STATUS_NOT_SWITCHABLE(" + STATUS_NOT_SWITCHABLE + "), " 296 + "STATUS_NOT_LOGGED_IN(" + STATUS_NOT_LOGGED_IN + ")"); 297 } 298 299 this.mAndroidFailureStatus = androidFailureStatus; 300 this.mErrorMessage = errorMessage; 301 302 // onConstructed(); // You can define this method to get a callback 303 } 304 305 /** 306 * Gets the user switch result status. 307 * 308 * @return either {@link UserSwitchResult#STATUS_SUCCESSFUL}, 309 * {@link UserSwitchResult#STATUS_ANDROID_FAILURE}, 310 * {@link UserSwitchResult#STATUS_HAL_FAILURE}, 311 * {@link UserSwitchResult#STATUS_HAL_INTERNAL_FAILURE}, 312 * {@link UserSwitchResult#STATUS_INVALID_REQUEST}, 313 * {@link UserSwitchResult#STATUS_UX_RESTRICTION_FAILURE}, 314 * {@link UserSwitchResult#STATUS_OK_USER_ALREADY_IN_FOREGROUND}, 315 * {@link UserSwitchResult#STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO}, 316 * {@link UserSwitchResult#STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST}, 317 * {@link UserSwitchResult#STATUS_NOT_SWITCHABLE}, or 318 * {@link UserSwitchResult#STATUS_NOT_LOGGED_IN}. 319 */ 320 @DataClass.Generated.Member getStatus()321 public @Status int getStatus() { 322 return mStatus; 323 } 324 325 /** 326 * Gets the failure status returned by {@link UserManager} when the {@link #getStatus() status} 327 * is {@link #STATUS_ANDROID_FAILURE}. 328 * 329 * @return {@code USER_OPERATION_ERROR_} constants defined by {@link UserManager}, or 330 * {@code null} when the {@link #getStatus() status} is not {@link #STATUS_ANDROID_FAILURE}. 331 */ 332 @DataClass.Generated.Member getAndroidFailureStatus()333 public @Nullable Integer getAndroidFailureStatus() { 334 return mAndroidFailureStatus; 335 } 336 337 /** 338 * Gets the error message, if any. 339 */ 340 @DataClass.Generated.Member getErrorMessage()341 public @Nullable String getErrorMessage() { 342 return mErrorMessage; 343 } 344 345 @Override 346 @DataClass.Generated.Member toString()347 public String toString() { 348 // You can override field toString logic by defining methods like: 349 // String fieldNameToString() { ... } 350 351 return "UserSwitchResult { " + 352 "status = " + statusToString(mStatus) + ", " + 353 "androidFailureStatus = " + mAndroidFailureStatus + ", " + 354 "errorMessage = " + mErrorMessage + 355 " }"; 356 } 357 358 @Override 359 @DataClass.Generated.Member writeToParcel(@ndroid.annotation.NonNull android.os.Parcel dest, int flags)360 public void writeToParcel(@android.annotation.NonNull android.os.Parcel dest, int flags) { 361 // You can override field parcelling by defining methods like: 362 // void parcelFieldName(Parcel dest, int flags) { ... } 363 364 byte flg = 0; 365 if (mAndroidFailureStatus != null) flg |= 0x2; 366 if (mErrorMessage != null) flg |= 0x4; 367 dest.writeByte(flg); 368 dest.writeInt(mStatus); 369 if (mAndroidFailureStatus != null) dest.writeInt(mAndroidFailureStatus); 370 if (mErrorMessage != null) dest.writeString(mErrorMessage); 371 } 372 373 /** @hide */ 374 @SuppressWarnings({"unchecked", "RedundantCast"}) 375 @DataClass.Generated.Member UserSwitchResult(@ndroid.annotation.NonNull android.os.Parcel in)376 /* package-private */ UserSwitchResult(@android.annotation.NonNull android.os.Parcel in) { 377 // You can override field unparcelling by defining methods like: 378 // static FieldType unparcelFieldName(Parcel in) { ... } 379 380 byte flg = in.readByte(); 381 int status = in.readInt(); 382 Integer androidFailureStatus = (flg & 0x2) == 0 ? null : (Integer) in.readInt(); 383 String errorMessage = (flg & 0x4) == 0 ? null : in.readString(); 384 385 this.mStatus = status; 386 387 if (!(mStatus == STATUS_SUCCESSFUL) 388 && !(mStatus == STATUS_ANDROID_FAILURE) 389 && !(mStatus == STATUS_HAL_FAILURE) 390 && !(mStatus == STATUS_HAL_INTERNAL_FAILURE) 391 && !(mStatus == STATUS_INVALID_REQUEST) 392 && !(mStatus == STATUS_UX_RESTRICTION_FAILURE) 393 && !(mStatus == STATUS_OK_USER_ALREADY_IN_FOREGROUND) 394 && !(mStatus == STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO) 395 && !(mStatus == STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST) 396 && !(mStatus == STATUS_NOT_SWITCHABLE) 397 && !(mStatus == STATUS_NOT_LOGGED_IN)) { 398 throw new java.lang.IllegalArgumentException( 399 "status was " + mStatus + " but must be one of: " 400 + "STATUS_SUCCESSFUL(" + STATUS_SUCCESSFUL + "), " 401 + "STATUS_ANDROID_FAILURE(" + STATUS_ANDROID_FAILURE + "), " 402 + "STATUS_HAL_FAILURE(" + STATUS_HAL_FAILURE + "), " 403 + "STATUS_HAL_INTERNAL_FAILURE(" + STATUS_HAL_INTERNAL_FAILURE + "), " 404 + "STATUS_INVALID_REQUEST(" + STATUS_INVALID_REQUEST + "), " 405 + "STATUS_UX_RESTRICTION_FAILURE(" + STATUS_UX_RESTRICTION_FAILURE + "), " 406 + "STATUS_OK_USER_ALREADY_IN_FOREGROUND(" + STATUS_OK_USER_ALREADY_IN_FOREGROUND + "), " 407 + "STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO(" + STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO + "), " 408 + "STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST(" + STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST + "), " 409 + "STATUS_NOT_SWITCHABLE(" + STATUS_NOT_SWITCHABLE + "), " 410 + "STATUS_NOT_LOGGED_IN(" + STATUS_NOT_LOGGED_IN + ")"); 411 } 412 413 this.mAndroidFailureStatus = androidFailureStatus; 414 this.mErrorMessage = errorMessage; 415 416 // onConstructed(); // You can define this method to get a callback 417 } 418 419 @DataClass.Generated.Member 420 public static final @android.annotation.NonNull Parcelable.Creator<UserSwitchResult> CREATOR 421 = new Parcelable.Creator<UserSwitchResult>() { 422 @Override 423 public UserSwitchResult[] newArray(int size) { 424 return new UserSwitchResult[size]; 425 } 426 427 @Override 428 public UserSwitchResult createFromParcel(@android.annotation.NonNull android.os.Parcel in) { 429 return new UserSwitchResult(in); 430 } 431 }; 432 433 @DataClass.Generated( 434 time = 1673057752058L, 435 codegenVersion = "1.0.23", 436 sourceFile = "packages/services/Car/car-lib/src/android/car/user/UserSwitchResult.java", 437 inputSignatures = "public static final @android.car.user.UserSwitchResult.Status @android.car.annotation.AddedInOrBefore int STATUS_SUCCESSFUL\npublic static final @android.car.user.UserSwitchResult.Status @android.car.annotation.AddedInOrBefore int STATUS_ANDROID_FAILURE\npublic static final @android.car.user.UserSwitchResult.Status @android.car.annotation.AddedInOrBefore int STATUS_HAL_FAILURE\npublic static final @android.car.user.UserSwitchResult.Status @android.car.annotation.AddedInOrBefore int STATUS_HAL_INTERNAL_FAILURE\npublic static final @android.car.user.UserSwitchResult.Status @android.car.annotation.AddedInOrBefore int STATUS_INVALID_REQUEST\npublic static final @android.car.user.UserSwitchResult.Status @android.car.annotation.AddedInOrBefore int STATUS_UX_RESTRICTION_FAILURE\npublic static final @android.car.user.UserSwitchResult.Status @android.car.annotation.AddedInOrBefore int STATUS_OK_USER_ALREADY_IN_FOREGROUND\npublic static final @android.car.user.UserSwitchResult.Status @android.car.annotation.AddedInOrBefore int STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO\npublic static final @android.car.user.UserSwitchResult.Status @android.car.annotation.AddedInOrBefore int STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST\npublic static final @android.car.user.UserSwitchResult.Status @android.car.annotation.AddedInOrBefore int STATUS_NOT_SWITCHABLE\npublic static final @android.car.user.UserSwitchResult.Status @android.car.annotation.AddedInOrBefore int STATUS_NOT_LOGGED_IN\nprivate final @android.car.user.UserSwitchResult.Status int mStatus\nprivate final @android.annotation.Nullable java.lang.Integer mAndroidFailureStatus\nprivate final @android.annotation.Nullable java.lang.String mErrorMessage\npublic @java.lang.Override @android.car.annotation.AddedInOrBefore boolean isSuccess()\npublic @java.lang.Override @com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport @android.car.annotation.AddedInOrBefore int describeContents()\nclass UserSwitchResult extends java.lang.Object implements [android.os.Parcelable, android.car.user.OperationResult]\n@com.android.car.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)") 438 @Deprecated __metadata()439 private void __metadata() {} 440 441 442 //@formatter:on 443 // End of generated code 444 445 } 446