1 /* 2 * Copyright (C) 2015 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 com.android.car; 18 19 import static android.car.user.CarUserManager.lifecycleEventTypeToString; 20 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 21 import static android.os.Process.INVALID_UID; 22 23 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.BOILERPLATE_CODE; 24 import static com.android.car.internal.util.VersionUtils.isPlatformVersionAtLeastU; 25 26 import android.annotation.NonNull; 27 import android.annotation.Nullable; 28 import android.annotation.SuppressLint; 29 import android.annotation.UserIdInt; 30 import android.app.ActivityManager; 31 import android.app.ActivityOptions; 32 import android.car.Car; 33 import android.car.builtin.content.ContextHelper; 34 import android.car.builtin.content.pm.PackageManagerHelper; 35 import android.car.builtin.os.UserManagerHelper; 36 import android.car.builtin.util.Slogf; 37 import android.car.user.CarUserManager.UserLifecycleEvent; 38 import android.content.ComponentName; 39 import android.content.ContentResolver; 40 import android.content.Context; 41 import android.content.Intent; 42 import android.content.ServiceConnection; 43 import android.content.pm.PackageManager; 44 import android.hardware.automotive.vehicle.SubscribeOptions; 45 import android.net.Uri; 46 import android.os.Binder; 47 import android.os.Handler; 48 import android.os.HandlerThread; 49 import android.os.IBinder; 50 import android.os.Looper; 51 import android.os.Process; 52 import android.os.SystemClock; 53 import android.os.UserHandle; 54 import android.os.UserManager; 55 import android.security.keystore.KeyGenParameterSpec; 56 import android.security.keystore.KeyProperties; 57 import android.util.ArrayMap; 58 import android.util.ArraySet; 59 import android.util.Log; 60 61 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport; 62 import com.android.car.internal.common.CommonConstants.UserLifecycleEventType; 63 import com.android.internal.annotations.VisibleForTesting; 64 import com.android.internal.util.Preconditions; 65 66 import java.io.ByteArrayOutputStream; 67 import java.io.IOException; 68 import java.nio.ByteBuffer; 69 import java.nio.ByteOrder; 70 import java.security.KeyStore; 71 import java.security.KeyStore.SecretKeyEntry; 72 import java.util.ArrayList; 73 import java.util.Arrays; 74 import java.util.List; 75 import java.util.Objects; 76 import java.util.UUID; 77 import java.util.concurrent.ThreadLocalRandom; 78 import java.util.stream.Collectors; 79 80 import javax.crypto.Cipher; 81 import javax.crypto.KeyGenerator; 82 import javax.crypto.SecretKey; 83 import javax.crypto.spec.GCMParameterSpec; 84 85 /** Utility class */ 86 public final class CarServiceUtils { 87 88 // https://developer.android.com/reference/java/util/UUID 89 private static final int UUID_LENGTH = 16; 90 private static final String TAG = CarLog.tagFor(CarServiceUtils.class); 91 private static final boolean DBG = Slogf.isLoggable(TAG, Log.DEBUG); 92 93 /** Empty int array */ 94 public static final int[] EMPTY_INT_ARRAY = new int[0]; 95 private static final String COMMON_HANDLER_THREAD_NAME = 96 "CarServiceUtils_COMMON_HANDLER_THREAD"; 97 private static final byte[] CHAR_POOL_FOR_RANDOM_STRING = 98 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes(); 99 100 private static final String PACKAGE_NOT_FOUND = "Package not found:"; 101 private static final String ANDROID_KEYSTORE_NAME = "AndroidKeyStore"; 102 private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding"; 103 private static final int GCM_TAG_LENGTH = 128; 104 105 /** K: class name, V: HandlerThread */ 106 private static final ArrayMap<String, HandlerThread> sHandlerThreads = new ArrayMap<>(); 107 108 @ExcludeFromCodeCoverageGeneratedReport(reason = BOILERPLATE_CODE, 109 details = "private constructor") CarServiceUtils()110 private CarServiceUtils() { 111 throw new UnsupportedOperationException("contains only static methods"); 112 } 113 114 /** 115 * Returns a byte buffer corresponding to the passed long argument. 116 * 117 * @param primitive data to convert format. 118 */ longToBytes(long primitive)119 public static byte[] longToBytes(long primitive) { 120 ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); 121 buffer.putLong(primitive); 122 return buffer.array(); 123 } 124 125 /** 126 * Returns a byte buffer corresponding to the passed long argument. 127 * 128 * @param array data to convert format. 129 */ bytesToLong(byte[] array)130 public static long bytesToLong(byte[] array) { 131 ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE); 132 buffer.put(array); 133 buffer.flip(); 134 long value = buffer.getLong(); 135 return value; 136 } 137 138 /** 139 * Returns a String in Hex format that is formed from the bytes in the byte array 140 * Useful for debugging 141 * 142 * @param array the byte array 143 * @return the Hex string version of the input byte array 144 */ byteArrayToHexString(byte[] array)145 public static String byteArrayToHexString(byte[] array) { 146 StringBuilder sb = new StringBuilder(array.length * 2); 147 for (byte b : array) { 148 sb.append(String.format("%02x", b)); 149 } 150 return sb.toString(); 151 } 152 153 /** 154 * Convert UUID to Big Endian byte array 155 * 156 * @param uuid UUID to convert 157 * @return the byte array representing the UUID 158 */ 159 @NonNull uuidToBytes(@onNull UUID uuid)160 public static byte[] uuidToBytes(@NonNull UUID uuid) { 161 162 return ByteBuffer.allocate(UUID_LENGTH) 163 .order(ByteOrder.BIG_ENDIAN) 164 .putLong(uuid.getMostSignificantBits()) 165 .putLong(uuid.getLeastSignificantBits()) 166 .array(); 167 } 168 169 /** 170 * Convert Big Endian byte array to UUID 171 * 172 * @param bytes byte array to convert 173 * @return the UUID representing the byte array, or null if not a valid UUID 174 */ 175 @Nullable bytesToUUID(@onNull byte[] bytes)176 public static UUID bytesToUUID(@NonNull byte[] bytes) { 177 if (bytes.length != UUID_LENGTH) { 178 return null; 179 } 180 181 ByteBuffer buffer = ByteBuffer.wrap(bytes); 182 return new UUID(buffer.getLong(), buffer.getLong()); 183 } 184 185 /** 186 * Generate a random zero-filled string of given length 187 * 188 * @param length of string 189 * @return generated string 190 */ 191 @SuppressLint("DefaultLocale") // Should always have the same format regardless of locale generateRandomNumberString(int length)192 public static String generateRandomNumberString(int length) { 193 return String.format("%0" + length + "d", 194 ThreadLocalRandom.current().nextInt((int) Math.pow(10, length))); 195 } 196 197 /** 198 * Concatentate the given 2 byte arrays 199 * 200 * @param a input array 1 201 * @param b input array 2 202 * @return concatenated array of arrays 1 and 2 203 */ 204 @Nullable concatByteArrays(@ullable byte[] a, @Nullable byte[] b)205 public static byte[] concatByteArrays(@Nullable byte[] a, @Nullable byte[] b) { 206 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 207 try { 208 if (a != null) { 209 outputStream.write(a); 210 } 211 if (b != null) { 212 outputStream.write(b); 213 } 214 } catch (IOException e) { 215 return null; 216 } 217 return outputStream.toByteArray(); 218 } 219 220 /** 221 * Returns the content resolver for the given user. This can be used to put/get the 222 * user's settings. 223 * 224 * @param context The context of the package. 225 * @param userId The id of the user which the content resolver is being requested for. It also 226 * accepts {@link UserHandle#USER_CURRENT}. 227 */ getContentResolverForUser(Context context, @UserIdInt int userId)228 public static ContentResolver getContentResolverForUser(Context context, 229 @UserIdInt int userId) { 230 if (userId == UserHandle.CURRENT.getIdentifier()) { 231 userId = ActivityManager.getCurrentUser(); 232 } 233 return context 234 .createContextAsUser( 235 UserHandle.of(userId), /* flags= */ 0) 236 .getContentResolver(); 237 } 238 239 /** 240 * Checks if the type of the {@code event} matches {@code expectedType}. 241 * 242 * @param tag The tag for logging. 243 * @param event The event to check the type against {@code expectedType}. 244 * @param expectedType The expected event type. 245 * @return true if {@code event}'s type matches {@code expectedType}. 246 * Otherwise, log a wtf and return false. 247 */ isEventOfType(String tag, UserLifecycleEvent event, @UserLifecycleEventType int expectedType)248 public static boolean isEventOfType(String tag, UserLifecycleEvent event, 249 @UserLifecycleEventType int expectedType) { 250 if (event.getEventType() == expectedType) { 251 return true; 252 } 253 Slogf.wtf(tag, "Received an unexpected event: %s. Expected type: %s.", event, 254 lifecycleEventTypeToString(expectedType)); 255 return false; 256 } 257 258 /** 259 * Checks if the type of the {@code event} is one of the types in {@code expectedTypes}. 260 * 261 * @param tag The tag for logging. 262 * @param event The event to check the type against {@code expectedTypes}. 263 * @param expectedTypes The expected event types. Must not be empty. 264 * @return true if {@code event}'s type can be found in {@code expectedTypes}. 265 * Otherwise, log a wtf and return false. 266 */ isEventAnyOfTypes(String tag, UserLifecycleEvent event, @UserLifecycleEventType int... expectedTypes)267 public static boolean isEventAnyOfTypes(String tag, UserLifecycleEvent event, 268 @UserLifecycleEventType int... expectedTypes) { 269 for (int i = 0; i < expectedTypes.length; i++) { 270 if (event.getEventType() == expectedTypes[i]) { 271 return true; 272 } 273 } 274 Slogf.wtf(tag, "Received an unexpected event: %s. Expected types: [%s]", event, 275 Arrays.stream(expectedTypes).mapToObj(t -> lifecycleEventTypeToString(t)).collect( 276 Collectors.joining(","))); 277 return false; 278 } 279 280 /** 281 * Checks if the calling UID owns the give package. 282 * 283 * @throws SecurityException if the calling UID doesn't own the given package. 284 */ checkCalledByPackage(Context context, String packageName)285 public static void checkCalledByPackage(Context context, String packageName) { 286 int callingUid = Binder.getCallingUid(); 287 PackageManager pm = context.getPackageManager(); 288 int uidFromPm = INVALID_UID; 289 try { 290 uidFromPm = PackageManagerHelper.getPackageUidAsUser(pm, packageName, 291 UserManagerHelper.getUserId(callingUid)); 292 } catch (PackageManager.NameNotFoundException e) { 293 String msg = PACKAGE_NOT_FOUND + packageName; 294 throw new SecurityException(msg, e); 295 } 296 297 if (uidFromPm != callingUid) { 298 throw new SecurityException( 299 "Package " + packageName + " is not associated to UID " + callingUid); 300 } 301 } 302 303 /** 304 * Execute a runnable on the main thread 305 * 306 * @param action The code to run on the main thread. 307 */ runOnMain(Runnable action)308 public static void runOnMain(Runnable action) { 309 runOnLooper(Looper.getMainLooper(), action); 310 } 311 312 /** 313 * Execute a runnable in the given looper 314 * @param looper Looper to run the action. 315 * @param action The code to run. 316 */ runOnLooper(Looper looper, Runnable action)317 public static void runOnLooper(Looper looper, Runnable action) { 318 new Handler(looper).post(action); 319 } 320 321 /** 322 * Execute an empty runnable in the looper of the handler thread 323 * specified by the name. 324 * 325 * @param name Name of the handler thread in which to run the empty 326 * runnable. 327 */ runEmptyRunnableOnLooperSync(String name)328 public static void runEmptyRunnableOnLooperSync(String name) { 329 runOnLooperSync(getHandlerThread(name).getLooper(), () -> {}); 330 } 331 332 /** 333 * Execute a call on the application's main thread, blocking until it is 334 * complete. Useful for doing things that are not thread-safe, such as 335 * looking at or modifying the view hierarchy. 336 * 337 * @param action The code to run on the main thread. 338 */ runOnMainSync(Runnable action)339 public static void runOnMainSync(Runnable action) { 340 runOnLooperSync(Looper.getMainLooper(), action); 341 } 342 343 /** 344 * Execute a delayed call on the application's main thread, blocking until it is 345 * complete. See {@link #runOnMainSync(Runnable)} 346 * 347 * @param action The code to run on the main thread. 348 * @param delayMillis The delay (in milliseconds) until the Runnable will be executed. 349 */ runOnMainSyncDelayed(Runnable action, long delayMillis)350 public static void runOnMainSyncDelayed(Runnable action, long delayMillis) { 351 runOnLooperSyncDelayed(Looper.getMainLooper(), action, delayMillis); 352 } 353 354 /** 355 * Execute a call on the given Looper thread, blocking until it is 356 * complete. 357 * 358 * @param looper Looper to run the action. 359 * @param action The code to run on the looper thread. 360 */ runOnLooperSync(Looper looper, Runnable action)361 public static void runOnLooperSync(Looper looper, Runnable action) { 362 runOnLooperSyncDelayed(looper, action, /* delayMillis */ 0L); 363 } 364 365 /** 366 * Executes a delayed call on the given Looper thread, blocking until it is complete. 367 * 368 * @param looper Looper to run the action. 369 * @param action The code to run on the looper thread. 370 * @param delayMillis The delay (in milliseconds) until the Runnable will be executed. 371 */ runOnLooperSyncDelayed(Looper looper, Runnable action, long delayMillis)372 public static void runOnLooperSyncDelayed(Looper looper, Runnable action, long delayMillis) { 373 if (Looper.myLooper() == looper) { 374 // requested thread is the same as the current thread. call directly. 375 action.run(); 376 } else { 377 Handler handler = new Handler(looper); 378 SyncRunnable sr = new SyncRunnable(action); 379 handler.postDelayed(sr, delayMillis); 380 sr.waitForComplete(); 381 } 382 } 383 384 /** 385 * Executes a runnable on the common thread. Useful for doing any kind of asynchronous work 386 * across the car related code that doesn't need to be on the main thread. 387 * 388 * @param action The code to run on the common thread. 389 */ runOnCommon(Runnable action)390 public static void runOnCommon(Runnable action) { 391 runOnLooper(getCommonHandlerThread().getLooper(), action); 392 } 393 394 private static final class SyncRunnable implements Runnable { 395 private final Runnable mTarget; 396 private volatile boolean mComplete = false; 397 SyncRunnable(Runnable target)398 public SyncRunnable(Runnable target) { 399 mTarget = target; 400 } 401 402 @Override run()403 public void run() { 404 mTarget.run(); 405 synchronized (this) { 406 mComplete = true; 407 notifyAll(); 408 } 409 } 410 waitForComplete()411 public void waitForComplete() { 412 synchronized (this) { 413 while (!mComplete) { 414 try { 415 wait(); 416 } catch (InterruptedException e) { 417 } 418 } 419 } 420 } 421 } 422 toFloatArray(List<Float> list)423 public static float[] toFloatArray(List<Float> list) { 424 int size = list.size(); 425 float[] array = new float[size]; 426 for (int i = 0; i < size; ++i) { 427 array[i] = list.get(i); 428 } 429 return array; 430 } 431 toLongArray(List<Long> list)432 public static long[] toLongArray(List<Long> list) { 433 int size = list.size(); 434 long[] array = new long[size]; 435 for (int i = 0; i < size; ++i) { 436 array[i] = list.get(i); 437 } 438 return array; 439 } 440 toIntArray(List<Integer> list)441 public static int[] toIntArray(List<Integer> list) { 442 int size = list.size(); 443 int[] array = new int[size]; 444 for (int i = 0; i < size; ++i) { 445 array[i] = list.get(i); 446 } 447 return array; 448 } 449 450 /** 451 * Converts array to an array list 452 */ asList(int[] array)453 public static ArrayList<Integer> asList(int[] array) { 454 Preconditions.checkArgument(array != null, "Array to convert to list can not be null"); 455 int size = array.length; 456 ArrayList<Integer> results = new ArrayList<>(size); 457 for (int i = 0; i < size; i++) { 458 results.add(array[i]); 459 } 460 return results; 461 } 462 toByteArray(List<Byte> list)463 public static byte[] toByteArray(List<Byte> list) { 464 int size = list.size(); 465 byte[] array = new byte[size]; 466 for (int i = 0; i < size; ++i) { 467 array[i] = list.get(i); 468 } 469 return array; 470 } 471 472 /** 473 * Converts values array to array set 474 */ toIntArraySet(int[] values)475 public static ArraySet<Integer> toIntArraySet(int[] values) { 476 Preconditions.checkArgument(values != null, 477 "Values to convert to array set must not be null"); 478 ArraySet<Integer> set = new ArraySet<>(values.length); 479 for (int c = 0; c < values.length; c++) { 480 set.add(values[c]); 481 } 482 483 return set; 484 } 485 486 /** 487 * Returns delta between elapsed time to uptime = {@link SystemClock#elapsedRealtime()} - 488 * {@link SystemClock#uptimeMillis()}. Note that this value will be always >= 0. 489 */ getUptimeToElapsedTimeDeltaInMillis()490 public static long getUptimeToElapsedTimeDeltaInMillis() { 491 int retry = 0; 492 int max_retry = 2; // try only up to twice 493 while (true) { 494 long elapsed1 = SystemClock.elapsedRealtime(); 495 long uptime = SystemClock.uptimeMillis(); 496 long elapsed2 = SystemClock.elapsedRealtime(); 497 if (elapsed1 == elapsed2) { // avoid possible 1 ms fluctuation. 498 return elapsed1 - uptime; 499 } 500 retry++; 501 if (retry >= max_retry) { 502 return elapsed1 - uptime; 503 } 504 } 505 } 506 507 /** 508 * Gets a static instance of {@code HandlerThread} for the given {@code name}. If the thread 509 * does not exist, create one and start it before returning. 510 */ getHandlerThread(String name)511 public static HandlerThread getHandlerThread(String name) { 512 synchronized (sHandlerThreads) { 513 HandlerThread thread = sHandlerThreads.get(name); 514 if (thread == null || !thread.isAlive()) { 515 Slogf.i(TAG, "Starting HandlerThread:" + name); 516 thread = new HandlerThread(name); 517 thread.start(); 518 sHandlerThreads.put(name, thread); 519 } 520 return thread; 521 } 522 } 523 524 /** 525 * Gets the static instance of the common {@code HandlerThread} meant to be used across 526 * CarService. 527 */ getCommonHandlerThread()528 public static HandlerThread getCommonHandlerThread() { 529 return getHandlerThread(COMMON_HANDLER_THREAD_NAME); 530 } 531 532 /** 533 * Finishes all queued {@code Handler} tasks for {@code HandlerThread} created via 534 * {@link#getHandlerThread(String)}. This is useful only for testing. 535 */ 536 @VisibleForTesting finishAllHandlerTasks()537 public static void finishAllHandlerTasks() { 538 ArrayList<HandlerThread> threads; 539 synchronized (sHandlerThreads) { 540 threads = new ArrayList<>(sHandlerThreads.values()); 541 } 542 ArrayList<SyncRunnable> syncs = new ArrayList<>(threads.size()); 543 for (int i = 0; i < threads.size(); i++) { 544 if (!threads.get(i).isAlive()) { 545 continue; 546 } 547 Handler handler = new Handler(threads.get(i).getLooper()); 548 SyncRunnable sr = new SyncRunnable(() -> { }); 549 if (handler.post(sr)) { 550 // Track the threads only where SyncRunnable is posted successfully. 551 syncs.add(sr); 552 } 553 } 554 for (int i = 0; i < syncs.size(); i++) { 555 syncs.get(i).waitForComplete(); 556 } 557 } 558 559 /** 560 * Assert if binder call is coming from system process like system server or if it is called 561 * from its own process even if it is not system. The latter can happen in test environment. 562 * Note that car service runs as system user but test like car service test will not. 563 */ assertCallingFromSystemProcessOrSelf()564 public static void assertCallingFromSystemProcessOrSelf() { 565 if (isCallingFromSystemProcessOrSelf()) { 566 throw new SecurityException("Only allowed from system or self"); 567 } 568 } 569 570 /** 571 * @return true if binder call is coming from system process like system server or if it is 572 * called from its own process even if it is not system. 573 */ isCallingFromSystemProcessOrSelf()574 public static boolean isCallingFromSystemProcessOrSelf() { 575 int uid = Binder.getCallingUid(); 576 int pid = Binder.getCallingPid(); 577 return uid != Process.SYSTEM_UID && pid != Process.myPid(); 578 } 579 580 581 /** Utility for checking permission */ assertVehicleHalMockPermission(Context context)582 public static void assertVehicleHalMockPermission(Context context) { 583 assertPermission(context, Car.PERMISSION_MOCK_VEHICLE_HAL); 584 } 585 586 /** Utility for checking permission */ assertNavigationManagerPermission(Context context)587 public static void assertNavigationManagerPermission(Context context) { 588 assertPermission(context, Car.PERMISSION_CAR_NAVIGATION_MANAGER); 589 } 590 591 /** Utility for checking permission */ assertClusterManagerPermission(Context context)592 public static void assertClusterManagerPermission(Context context) { 593 assertPermission(context, Car.PERMISSION_CAR_INSTRUMENT_CLUSTER_CONTROL); 594 } 595 596 /** Utility for checking permission */ assertPowerPermission(Context context)597 public static void assertPowerPermission(Context context) { 598 assertPermission(context, Car.PERMISSION_CAR_POWER); 599 } 600 601 /** Utility for checking permission */ assertProjectionPermission(Context context)602 public static void assertProjectionPermission(Context context) { 603 assertPermission(context, Car.PERMISSION_CAR_PROJECTION); 604 } 605 606 /** Verify the calling context has the {@link Car#PERMISSION_CAR_PROJECTION_STATUS} */ assertProjectionStatusPermission(Context context)607 public static void assertProjectionStatusPermission(Context context) { 608 assertPermission(context, Car.PERMISSION_CAR_PROJECTION_STATUS); 609 } 610 611 /** Utility for checking permission */ assertAnyDiagnosticPermission(Context context)612 public static void assertAnyDiagnosticPermission(Context context) { 613 assertAnyPermission(context, 614 Car.PERMISSION_CAR_DIAGNOSTIC_READ_ALL, 615 Car.PERMISSION_CAR_DIAGNOSTIC_CLEAR); 616 } 617 618 /** Utility for checking permission */ assertDrivingStatePermission(Context context)619 public static void assertDrivingStatePermission(Context context) { 620 assertPermission(context, Car.PERMISSION_CAR_DRIVING_STATE); 621 } 622 623 /** 624 * Verify the calling context has either {@link Car#PERMISSION_VMS_SUBSCRIBER} or 625 * {@link Car#PERMISSION_VMS_PUBLISHER} 626 */ assertAnyVmsPermission(Context context)627 public static void assertAnyVmsPermission(Context context) { 628 assertAnyPermission(context, 629 Car.PERMISSION_VMS_SUBSCRIBER, 630 Car.PERMISSION_VMS_PUBLISHER); 631 } 632 633 /** Utility for checking permission */ assertVmsPublisherPermission(Context context)634 public static void assertVmsPublisherPermission(Context context) { 635 assertPermission(context, Car.PERMISSION_VMS_PUBLISHER); 636 } 637 638 /** Utility for checking permission */ assertVmsSubscriberPermission(Context context)639 public static void assertVmsSubscriberPermission(Context context) { 640 assertPermission(context, Car.PERMISSION_VMS_SUBSCRIBER); 641 } 642 643 /** Utility for checking permission */ assertPermission(Context context, String permission)644 public static void assertPermission(Context context, String permission) { 645 if (context.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { 646 throw new SecurityException("requires " + permission); 647 } 648 } 649 650 /** 651 * Checks to see if the caller has a permission. 652 * 653 * @return boolean TRUE if caller has the permission. 654 */ hasPermission(Context context, String permission)655 public static boolean hasPermission(Context context, String permission) { 656 return context.checkCallingOrSelfPermission(permission) 657 == PackageManager.PERMISSION_GRANTED; 658 } 659 660 /** Utility for checking permission */ assertAnyPermission(Context context, String... permissions)661 public static void assertAnyPermission(Context context, String... permissions) { 662 for (String permission : permissions) { 663 if (context.checkCallingOrSelfPermission(permission) 664 == PackageManager.PERMISSION_GRANTED) { 665 return; 666 } 667 } 668 throw new SecurityException("requires any of " + Arrays.toString(permissions)); 669 } 670 671 /** 672 * Turns a {@code SubscribeOptions} to {@code 673 * android.hardware.automotive.vehicle.V2_0.SubscribeOptions} 674 */ subscribeOptionsToHidl( SubscribeOptions options)675 public static android.hardware.automotive.vehicle.V2_0.SubscribeOptions subscribeOptionsToHidl( 676 SubscribeOptions options) { 677 android.hardware.automotive.vehicle.V2_0.SubscribeOptions hidlOptions = 678 new android.hardware.automotive.vehicle.V2_0.SubscribeOptions(); 679 hidlOptions.propId = options.propId; 680 hidlOptions.sampleRate = options.sampleRate; 681 // HIDL backend requires flags to be set although it is not used any more. 682 hidlOptions.flags = android.hardware.automotive.vehicle.V2_0.SubscribeFlags.EVENTS_FROM_CAR; 683 // HIDL backend does not support area IDs, so we ignore options.areaId field. 684 return hidlOptions; 685 } 686 687 /** 688 * Returns {@code true} if the current configuration supports multiple users on multiple 689 * displays. 690 */ isMultipleUsersOnMultipleDisplaysSupported(UserManager userManager)691 public static boolean isMultipleUsersOnMultipleDisplaysSupported(UserManager userManager) { 692 return isPlatformVersionAtLeastU() 693 && UserManagerHelper.isVisibleBackgroundUsersSupported(userManager); 694 } 695 696 /** 697 * Returns {@code true} if the current configuration supports visible background users on 698 * default display. 699 */ isVisibleBackgroundUsersOnDefaultDisplaySupported( UserManager userManager)700 public static boolean isVisibleBackgroundUsersOnDefaultDisplaySupported( 701 UserManager userManager) { 702 return isPlatformVersionAtLeastU() 703 && UserManagerHelper.isVisibleBackgroundUsersOnDefaultDisplaySupported(userManager); 704 } 705 706 /** 707 * Starts Activity for the given {@code userId} and {@code displayId}. 708 * 709 * @return {@code true} when starting activity succeeds. It can fail in situation like secondary 710 * home package not existing. 711 */ startHomeForUserAndDisplay(Context context, @UserIdInt int userId, int displayId)712 public static boolean startHomeForUserAndDisplay(Context context, 713 @UserIdInt int userId, int displayId) { 714 if (DBG) { 715 Slogf.d(TAG, "Starting HOME for user: %d, display:%d", userId, displayId); 716 } 717 Intent homeIntent = new Intent(Intent.ACTION_MAIN) 718 .addCategory(Intent.CATEGORY_HOME); 719 ActivityOptions activityOptions = ActivityOptions.makeBasic() 720 .setLaunchDisplayId(displayId); 721 try { 722 ContextHelper.startActivityAsUser(context, homeIntent, activityOptions.toBundle(), 723 UserHandle.of(userId)); 724 if (DBG) { 725 Slogf.d(TAG, "Started HOME for user: %d, display:%d", userId, displayId); 726 } 727 return true; 728 } catch (Exception e) { 729 Slogf.w(TAG, e, "Cannot start HOME for user: %d, display:%d", userId, displayId); 730 return false; 731 } 732 } 733 734 /** 735 * Starts SystemUI component for a particular user - should be called for non-current user only. 736 * 737 * @return {@code true} when starting service succeeds. It can fail in situation like the 738 * SystemUI service component not being defined. 739 */ startSystemUiForUser(Context context, @UserIdInt int userId)740 public static boolean startSystemUiForUser(Context context, @UserIdInt int userId) { 741 if (!isPlatformVersionAtLeastU()) { 742 return false; 743 } 744 if (DBG) Slogf.d(TAG, "Start SystemUI for user: %d", userId); 745 Preconditions.checkArgument(userId != UserHandle.SYSTEM.getIdentifier(), 746 "Cannot start SystemUI for the system user"); 747 Preconditions.checkArgument(userId != ActivityManager.getCurrentUser(), 748 "Cannot start SystemUI for the current foreground user"); 749 750 // TODO (b/261192740): add EventLog for SystemUI starting 751 ComponentName sysuiComponent = PackageManagerHelper.getSystemUiServiceComponent(context); 752 Intent sysUIIntent = new Intent().setComponent(sysuiComponent); 753 try { 754 context.bindServiceAsUser(sysUIIntent, sEmptyServiceConnection, 755 Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.of(userId)); 756 return true; 757 } catch (Exception e) { 758 Slogf.w(TAG, e, "Cannot start SysUI component %s for user %d", sysuiComponent, 759 userId); 760 return false; 761 } 762 } 763 764 // The callbacks are not called actually, because SystemUI returns null for IBinder. 765 private static final ServiceConnection sEmptyServiceConnection = new ServiceConnection() { 766 @Override 767 public void onServiceConnected(ComponentName name, IBinder service) {} 768 769 @Override 770 public void onServiceDisconnected(ComponentName name) {} 771 }; 772 773 /** 774 * Stops the SystemUI component for a particular user - this function should not be called 775 * for the system user. 776 */ stopSystemUiForUser(Context context, @UserIdInt int userId)777 public static void stopSystemUiForUser(Context context, @UserIdInt int userId) { 778 if (!isPlatformVersionAtLeastU()) { 779 return; 780 } 781 Preconditions.checkArgument(userId != UserHandle.SYSTEM.getIdentifier(), 782 "Cannot stop SystemUI for the system user"); 783 // TODO (b/261192740): add EventLog for SystemUI stopping 784 String sysUiPackage = PackageManagerHelper.getSystemUiPackageName(context); 785 PackageManagerHelper.forceStopPackageAsUserEvenWhenStopping(context, sysUiPackage, userId); 786 } 787 788 /** 789 * Starts UserPickerActivity for the given {@code userId} and {@code displayId}. 790 * 791 * @return {@code true} when starting activity succeeds. It can fail in situation like 792 * package not existing. 793 */ startUserPickerOnDisplay(Context context, int displayId, String userPickerActivityPackage)794 public static boolean startUserPickerOnDisplay(Context context, 795 int displayId, String userPickerActivityPackage) { 796 if (DBG) { 797 Slogf.d(TAG, "Starting user picker on display:%d", displayId); 798 } 799 // FLAG_ACTIVITY_MULTIPLE_TASK ensures the user picker can show up on multiple displays. 800 Intent intent = new Intent() 801 .setComponent(ComponentName.unflattenFromString( 802 userPickerActivityPackage)) 803 .addFlags(FLAG_ACTIVITY_NEW_TASK) 804 .setData(Uri.parse("data://com.android.car/userpicker/display" + displayId)); 805 ActivityOptions activityOptions = ActivityOptions.makeBasic() 806 .setLaunchDisplayId(displayId); 807 try { 808 // Start the user picker as user 0. 809 ContextHelper.startActivityAsUser(context, intent, activityOptions.toBundle(), 810 UserHandle.SYSTEM); 811 return true; 812 } catch (Exception e) { 813 Slogf.w(TAG, e, "Cannot start user picker as user 0 on display:%d", displayId); 814 return false; 815 } 816 } 817 818 /** 819 * Generates a random string which consists of captial letters and numbers. 820 */ 821 @SuppressLint("DefaultLocale") // Should always have the same format regardless of locale generateRandomAlphaNumericString(int length)822 public static String generateRandomAlphaNumericString(int length) { 823 StringBuilder sb = new StringBuilder(); 824 825 int poolSize = CHAR_POOL_FOR_RANDOM_STRING.length; 826 for (int i = 0; i < length; i++) { 827 sb.append(CHAR_POOL_FOR_RANDOM_STRING[ThreadLocalRandom.current().nextInt(poolSize)]); 828 } 829 return sb.toString(); 830 } 831 832 /** 833 * Encrypts byte array with the keys stored in {@code keyAlias} using AES. 834 * 835 * @return Encrypted data and initialization vector in {@link EncryptedData}. {@code null} in 836 * case of errors. 837 */ 838 @Nullable encryptData(byte[] data, String keyAlias)839 public static EncryptedData encryptData(byte[] data, String keyAlias) { 840 SecretKey secretKey = getOrCreateSecretKey(keyAlias); 841 if (secretKey == null) { 842 Slogf.e(TAG, "Failed to encrypt data: cannot get a secret key (keyAlias: %s)", 843 keyAlias); 844 return null; 845 } 846 try { 847 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); 848 cipher.init(Cipher.ENCRYPT_MODE, secretKey); 849 return new EncryptedData(cipher.doFinal(data), cipher.getIV()); 850 } catch (Exception e) { 851 Slogf.e(TAG, e, "Failed to encrypt data: keyAlias=%s", keyAlias); 852 return null; 853 } 854 } 855 856 /** 857 * Decrypts byte array with the keys stored in {@code keyAlias} using AES. 858 * 859 * @return Decrypted data in byte array. {@code null} in case of errors. 860 */ 861 @Nullable decryptData(EncryptedData data, String keyAlias)862 public static byte[] decryptData(EncryptedData data, String keyAlias) { 863 SecretKey secretKey = getOrCreateSecretKey(keyAlias); 864 if (secretKey == null) { 865 Slogf.e(TAG, "Failed to decrypt data: cannot get a secret key (keyAlias: %s)", 866 keyAlias); 867 return null; 868 } 869 try { 870 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); 871 GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, data.getIv()); 872 cipher.init(Cipher.DECRYPT_MODE, secretKey, spec); 873 return cipher.doFinal(data.getEncryptedData()); 874 } catch (Exception e) { 875 Slogf.e(TAG, e, "Failed to decrypt data: keyAlias=%s", keyAlias); 876 return null; 877 } 878 } 879 880 /** 881 * Class to hold encrypted data and its initialization vector. 882 */ 883 public static final class EncryptedData { 884 private final byte[] mEncryptedData; 885 private final byte[] mIv; 886 EncryptedData(byte[] encryptedData, byte[] iv)887 public EncryptedData(byte[] encryptedData, byte[] iv) { 888 mEncryptedData = encryptedData; 889 mIv = iv; 890 } 891 getEncryptedData()892 public byte[] getEncryptedData() { 893 return mEncryptedData; 894 } 895 getIv()896 public byte[] getIv() { 897 return mIv; 898 } 899 900 @Override equals(Object other)901 public boolean equals(Object other) { 902 if (this == other) return true; 903 if (!(other instanceof EncryptedData)) return false; 904 EncryptedData data = (EncryptedData) other; 905 return Arrays.equals(mEncryptedData, data.mEncryptedData) 906 && Arrays.equals(mIv, data.mIv); 907 } 908 909 @Override hashCode()910 public int hashCode() { 911 return Objects.hash(Arrays.hashCode(mEncryptedData), Arrays.hashCode(mIv)); 912 } 913 } 914 915 @Nullable getOrCreateSecretKey(String keyAlias)916 private static SecretKey getOrCreateSecretKey(String keyAlias) { 917 try { 918 KeyStore keyStore = KeyStore.getInstance(ANDROID_KEYSTORE_NAME); 919 keyStore.load(/* KeyStore.LoadStoreParameter= */ null); 920 if (keyStore.containsAlias(keyAlias)) { 921 SecretKeyEntry secretKeyEntry = (SecretKeyEntry) keyStore.getEntry(keyAlias, 922 /* protParam= */ null); 923 if (secretKeyEntry != null) { 924 return secretKeyEntry.getSecretKey(); 925 } 926 Slogf.e(TAG, "Android key store contains the alias (%s) but the secret key " 927 + "entry is null", keyAlias); 928 return null; 929 } 930 KeyGenerator keyGenerator = KeyGenerator.getInstance( 931 KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEYSTORE_NAME); 932 KeyGenParameterSpec keyGenParameterSpec = 933 new KeyGenParameterSpec.Builder(keyAlias, KeyProperties.PURPOSE_ENCRYPT 934 | KeyProperties.PURPOSE_DECRYPT) 935 .setBlockModes(KeyProperties.BLOCK_MODE_GCM) 936 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) 937 .build(); 938 keyGenerator.init(keyGenParameterSpec); 939 return keyGenerator.generateKey(); 940 } catch (Exception e) { 941 Slogf.e(TAG, "Failed to get or create a secret key for the alias (%s)", keyAlias); 942 return null; 943 } 944 } 945 } 946