1 /* 2 * Copyright (C) 2016 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.server.om; 18 19 import static android.app.AppGlobals.getPackageManager; 20 import static android.content.Intent.ACTION_OVERLAY_CHANGED; 21 import static android.content.Intent.ACTION_PACKAGE_ADDED; 22 import static android.content.Intent.ACTION_PACKAGE_CHANGED; 23 import static android.content.Intent.ACTION_PACKAGE_REMOVED; 24 import static android.content.Intent.ACTION_USER_ADDED; 25 import static android.content.Intent.ACTION_USER_REMOVED; 26 import static android.content.Intent.EXTRA_REASON; 27 import static android.content.om.OverlayManagerTransaction.Request.TYPE_REGISTER_FABRICATED; 28 import static android.content.om.OverlayManagerTransaction.Request.TYPE_SET_DISABLED; 29 import static android.content.om.OverlayManagerTransaction.Request.TYPE_SET_ENABLED; 30 import static android.content.om.OverlayManagerTransaction.Request.TYPE_UNREGISTER_FABRICATED; 31 import static android.content.pm.PackageManager.SIGNATURE_MATCH; 32 import static android.os.Trace.TRACE_TAG_RRO; 33 import static android.os.Trace.traceBegin; 34 import static android.os.Trace.traceEnd; 35 36 import static com.android.server.om.OverlayManagerServiceImpl.OperationFailedException; 37 38 import android.annotation.NonNull; 39 import android.annotation.Nullable; 40 import android.annotation.UserIdInt; 41 import android.app.ActivityManager; 42 import android.app.IActivityManager; 43 import android.content.BroadcastReceiver; 44 import android.content.Context; 45 import android.content.Intent; 46 import android.content.IntentFilter; 47 import android.content.om.IOverlayManager; 48 import android.content.om.OverlayIdentifier; 49 import android.content.om.OverlayInfo; 50 import android.content.om.OverlayManagerTransaction; 51 import android.content.om.OverlayableInfo; 52 import android.content.pm.IPackageManager; 53 import android.content.pm.PackageManagerInternal; 54 import android.content.pm.UserInfo; 55 import android.content.pm.overlay.OverlayPaths; 56 import android.content.res.ApkAssets; 57 import android.net.Uri; 58 import android.os.Binder; 59 import android.os.Environment; 60 import android.os.FabricatedOverlayInternal; 61 import android.os.HandlerThread; 62 import android.os.IBinder; 63 import android.os.Process; 64 import android.os.RemoteException; 65 import android.os.ResultReceiver; 66 import android.os.ShellCallback; 67 import android.os.SystemProperties; 68 import android.os.UserHandle; 69 import android.os.UserManager; 70 import android.text.TextUtils; 71 import android.util.ArrayMap; 72 import android.util.ArraySet; 73 import android.util.AtomicFile; 74 import android.util.Slog; 75 import android.util.SparseArray; 76 77 import com.android.internal.content.om.OverlayConfig; 78 import com.android.internal.util.ArrayUtils; 79 import com.android.internal.util.CollectionUtils; 80 import com.android.server.FgThread; 81 import com.android.server.LocalServices; 82 import com.android.server.SystemConfig; 83 import com.android.server.SystemService; 84 85 import com.android.server.pm.UserManagerService; 86 import com.android.server.pm.parsing.pkg.AndroidPackage; 87 88 import libcore.util.EmptyArray; 89 90 import org.xmlpull.v1.XmlPullParserException; 91 92 import java.io.File; 93 import java.io.FileDescriptor; 94 import java.io.FileInputStream; 95 import java.io.FileOutputStream; 96 import java.io.IOException; 97 import java.io.PrintWriter; 98 import java.util.ArrayList; 99 import java.util.Arrays; 100 import java.util.Collection; 101 import java.util.Collections; 102 import java.util.HashSet; 103 import java.util.List; 104 import java.util.Map; 105 import java.util.Objects; 106 import java.util.Set; 107 108 /** 109 * Service to manage asset overlays. 110 * 111 * <p>Asset overlays are additional resources that come from apks loaded 112 * alongside the system and app apks. This service, the OverlayManagerService 113 * (OMS), tracks which installed overlays to use and provides methods to change 114 * this. Changes propagate to running applications as part of the Activity 115 * lifecycle. This allows Activities to reread their resources at a well 116 * defined point.</p> 117 * 118 * <p>By itself, the OMS will not change what overlays should be active. 119 * Instead, it is only responsible for making sure that overlays *can* be used 120 * from a technical and security point of view and to activate overlays in 121 * response to external requests. The responsibility to toggle overlays on and 122 * off lies within components that implement different use-cases such as themes 123 * or dynamic customization.</p> 124 * 125 * <p>The OMS receives input from three sources:</p> 126 * 127 * <ul> 128 * <li>Callbacks from the SystemService class, specifically when the 129 * Android framework is booting and when the end user switches Android 130 * users.</li> 131 * 132 * <li>Intents from the PackageManagerService (PMS). Overlays are regular 133 * apks, and whenever a package is installed (or removed, or has a 134 * component enabled or disabled), the PMS broadcasts this as an intent. 135 * When the OMS receives one of these intents, it updates its internal 136 * representation of the available overlays and, if there was a visible 137 * change, triggers an asset refresh in the affected apps.</li> 138 * 139 * <li>External requests via the {@link IOverlayManager AIDL interface}. 140 * The interface allows clients to read information about the currently 141 * available overlays, change whether an overlay should be used or not, and 142 * change the relative order in which overlay packages are loaded. 143 * Read-access is granted if the request targets the same Android user as 144 * the caller runs as, or if the caller holds the 145 * INTERACT_ACROSS_USERS_FULL permission. Write-access is granted if the 146 * caller is granted read-access and additionaly holds the 147 * CHANGE_OVERLAY_PACKAGES permission.</li> 148 * </ul> 149 * 150 * <p>The AIDL interface works with String package names, int user IDs, and 151 * {@link OverlayInfo} objects. OverlayInfo instances are used to track a 152 * specific pair of target and overlay packages and include information such as 153 * the current state of the overlay. OverlayInfo objects are immutable.</p> 154 * 155 * <p>Internally, OverlayInfo objects are maintained by the 156 * OverlayManagerSettings class. The OMS and its helper classes are notified of 157 * changes to the settings by the OverlayManagerSettings.ChangeListener 158 * callback interface. The file /data/system/overlays.xml is used to persist 159 * the settings.</p> 160 * 161 * <p>Creation and deletion of idmap files are handled by the IdmapManager 162 * class.</p> 163 * 164 * <p>The following is an overview of OMS and its related classes. Note how box 165 * (2) does the heavy lifting, box (1) interacts with the Android framework, 166 * and box (3) replaces box (1) during unit testing.</p> 167 * 168 * <pre> 169 * Android framework 170 * | ^ 171 * . . . | . . . . | . . . . 172 * . | | . 173 * . AIDL, broadcasts . 174 * . intents | . 175 * . | | . . . . . . . . . . . . 176 * . v | . . 177 * . OverlayManagerService . OverlayManagerTests . 178 * . \ . / . 179 * . (1) \ . / (3) . 180 * . . . . . . . . . . \ . . . / . . . . . . . . . 181 * . \ / . 182 * . (2) \ / . 183 * . OverlayManagerServiceImpl . 184 * . | | . 185 * . | | . 186 * . OverlayManagerSettings IdmapManager . 187 * . . 188 * . . . . . . . . . . . . . . . . . . . . . . 189 * </pre> 190 * 191 * <p>To test the OMS, execute: 192 * <code> 193 * atest FrameworksServicesTests:com.android.server.om # internal tests 194 * atest OverlayDeviceTests OverlayHostTests # public API tests 195 * </code> 196 * </p> 197 * 198 * <p>Finally, here is a list of keywords used in the OMS context.</p> 199 * 200 * <ul> 201 * <li><b>target [package]</b> -- A regular apk that may have its resource 202 * pool extended by zero or more overlay packages.</li> 203 * 204 * <li><b>overlay [package]</b> -- An apk that provides additional 205 * resources to another apk.</li> 206 * 207 * <li><b>OMS</b> -- The OverlayManagerService, i.e. this class.</li> 208 * 209 * <li><b>approved</b> -- An overlay is approved if the OMS has verified 210 * that it can be used technically speaking (its target package is 211 * installed, at least one resource name in both packages match, the 212 * idmap was created, etc) and that it is secure to do so. External 213 * clients can not change this state.</li> 214 * 215 * <li><b>not approved</b> -- The opposite of approved.</li> 216 * 217 * <li><b>enabled</b> -- An overlay currently in active use and thus part 218 * of resource lookups. This requires the overlay to be approved. Only 219 * external clients can change this state.</li> 220 * 221 * <li><b>disabled</b> -- The opposite of enabled.</li> 222 * 223 * <li><b>idmap</b> -- A mapping of resource IDs between target and overlay 224 * used during resource lookup. Also the name of the binary that creates 225 * the mapping.</li> 226 * </ul> 227 */ 228 public final class OverlayManagerService extends SystemService { 229 static final String TAG = "OverlayManager"; 230 231 static final boolean DEBUG = false; 232 233 /** 234 * The system property that specifies the default overlays to apply. 235 * This is a semicolon separated list of package names. 236 * 237 * Ex: com.android.vendor.overlay_one;com.android.vendor.overlay_two 238 */ 239 private static final String DEFAULT_OVERLAYS_PROP = "ro.boot.vendor.overlay.theme"; 240 241 private final Object mLock = new Object(); 242 243 private final AtomicFile mSettingsFile; 244 245 private final PackageManagerHelperImpl mPackageManager; 246 247 private final UserManagerService mUserManager; 248 249 private final OverlayManagerSettings mSettings; 250 251 private final OverlayManagerServiceImpl mImpl; 252 253 private final OverlayActorEnforcer mActorEnforcer; 254 OverlayManagerService(@onNull final Context context)255 public OverlayManagerService(@NonNull final Context context) { 256 super(context); 257 try { 258 traceBegin(TRACE_TAG_RRO, "OMS#OverlayManagerService"); 259 mSettingsFile = new AtomicFile( 260 new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays"); 261 mPackageManager = new PackageManagerHelperImpl(context); 262 mUserManager = UserManagerService.getInstance(); 263 IdmapManager im = new IdmapManager(IdmapDaemon.getInstance(), mPackageManager); 264 mSettings = new OverlayManagerSettings(); 265 mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings, 266 OverlayConfig.getSystemInstance(), getDefaultOverlayPackages()); 267 mActorEnforcer = new OverlayActorEnforcer(mPackageManager); 268 269 HandlerThread packageReceiverThread = new HandlerThread(TAG); 270 packageReceiverThread.start(); 271 272 final IntentFilter packageFilter = new IntentFilter(); 273 packageFilter.addAction(ACTION_PACKAGE_ADDED); 274 packageFilter.addAction(ACTION_PACKAGE_CHANGED); 275 packageFilter.addAction(ACTION_PACKAGE_REMOVED); 276 packageFilter.addDataScheme("package"); 277 getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL, 278 packageFilter, null, packageReceiverThread.getThreadHandler()); 279 280 final IntentFilter userFilter = new IntentFilter(); 281 userFilter.addAction(ACTION_USER_ADDED); 282 userFilter.addAction(ACTION_USER_REMOVED); 283 getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL, 284 userFilter, null, null); 285 286 restoreSettings(); 287 288 initIfNeeded(); 289 onSwitchUser(UserHandle.USER_SYSTEM); 290 291 publishBinderService(Context.OVERLAY_SERVICE, mService); 292 publishLocalService(OverlayManagerService.class, this); 293 } finally { 294 traceEnd(TRACE_TAG_RRO); 295 } 296 } 297 298 @Override onStart()299 public void onStart() { 300 // Intentionally left empty. 301 } 302 initIfNeeded()303 private void initIfNeeded() { 304 final UserManager um = getContext().getSystemService(UserManager.class); 305 final List<UserInfo> users = um.getAliveUsers(); 306 synchronized (mLock) { 307 final int userCount = users.size(); 308 for (int i = 0; i < userCount; i++) { 309 final UserInfo userInfo = users.get(i); 310 if (!userInfo.supportsSwitchTo() && userInfo.id != UserHandle.USER_SYSTEM) { 311 // Initialize any users that can't be switched to, as their state would 312 // never be setup in onSwitchUser(). We will switch to the system user right 313 // after this, and its state will be setup there. 314 updatePackageManagerLocked(mImpl.updateOverlaysForUser(users.get(i).id)); 315 } 316 } 317 } 318 } 319 320 @Override onUserSwitching(@ullable TargetUser from, @NonNull TargetUser to)321 public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) { 322 onSwitchUser(to.getUserIdentifier()); 323 } 324 onSwitchUser(@serIdInt int newUserId)325 private void onSwitchUser(@UserIdInt int newUserId) { 326 try { 327 traceBegin(TRACE_TAG_RRO, "OMS#onSwitchUser " + newUserId); 328 // ensure overlays in the settings are up-to-date, and propagate 329 // any asset changes to the rest of the system 330 synchronized (mLock) { 331 updateTargetPackagesLocked(mImpl.updateOverlaysForUser(newUserId)); 332 } 333 } finally { 334 traceEnd(TRACE_TAG_RRO); 335 } 336 } 337 getDefaultOverlayPackages()338 private static String[] getDefaultOverlayPackages() { 339 final String str = SystemProperties.get(DEFAULT_OVERLAYS_PROP); 340 if (TextUtils.isEmpty(str)) { 341 return EmptyArray.STRING; 342 } 343 344 final ArraySet<String> defaultPackages = new ArraySet<>(); 345 for (String packageName : str.split(";")) { 346 if (!TextUtils.isEmpty(packageName)) { 347 defaultPackages.add(packageName); 348 } 349 } 350 return defaultPackages.toArray(new String[defaultPackages.size()]); 351 } 352 353 private final class PackageReceiver extends BroadcastReceiver { 354 @Override onReceive(@onNull final Context context, @NonNull final Intent intent)355 public void onReceive(@NonNull final Context context, @NonNull final Intent intent) { 356 final String action = intent.getAction(); 357 if (action == null) { 358 Slog.e(TAG, "Cannot handle package broadcast with null action"); 359 return; 360 } 361 final Uri data = intent.getData(); 362 if (data == null) { 363 Slog.e(TAG, "Cannot handle package broadcast with null data"); 364 return; 365 } 366 final String packageName = data.getSchemeSpecificPart(); 367 368 final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); 369 370 final int[] userIds; 371 final int extraUid = intent.getIntExtra(Intent.EXTRA_UID, UserHandle.USER_NULL); 372 if (extraUid == UserHandle.USER_NULL) { 373 userIds = mUserManager.getUserIds(); 374 } else { 375 userIds = new int[] { UserHandle.getUserId(extraUid) }; 376 } 377 378 switch (action) { 379 case ACTION_PACKAGE_ADDED: 380 if (replacing) { 381 onPackageReplaced(packageName, userIds); 382 } else { 383 onPackageAdded(packageName, userIds); 384 } 385 break; 386 case ACTION_PACKAGE_CHANGED: 387 // ignore the intent if it was sent by the package manager as a result of the 388 // overlay manager having sent ACTION_OVERLAY_CHANGED 389 if (!ACTION_OVERLAY_CHANGED.equals(intent.getStringExtra(EXTRA_REASON))) { 390 onPackageChanged(packageName, userIds); 391 } 392 break; 393 case ACTION_PACKAGE_REMOVED: 394 if (replacing) { 395 onPackageReplacing(packageName, userIds); 396 } else { 397 onPackageRemoved(packageName, userIds); 398 } 399 break; 400 default: 401 // do nothing 402 break; 403 } 404 } 405 onPackageAdded(@onNull final String packageName, @NonNull final int[] userIds)406 private void onPackageAdded(@NonNull final String packageName, 407 @NonNull final int[] userIds) { 408 try { 409 traceBegin(TRACE_TAG_RRO, "OMS#onPackageAdded " + packageName); 410 for (final int userId : userIds) { 411 synchronized (mLock) { 412 final AndroidPackage pkg = mPackageManager.onPackageAdded( 413 packageName, userId); 414 if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) { 415 try { 416 updateTargetPackagesLocked( 417 mImpl.onPackageAdded(packageName, userId)); 418 } catch (OperationFailedException e) { 419 Slog.e(TAG, "onPackageAdded internal error", e); 420 } 421 } 422 } 423 } 424 } finally { 425 traceEnd(TRACE_TAG_RRO); 426 } 427 } 428 onPackageChanged(@onNull final String packageName, @NonNull final int[] userIds)429 private void onPackageChanged(@NonNull final String packageName, 430 @NonNull final int[] userIds) { 431 try { 432 traceBegin(TRACE_TAG_RRO, "OMS#onPackageChanged " + packageName); 433 for (int userId : userIds) { 434 synchronized (mLock) { 435 final AndroidPackage pkg = mPackageManager.onPackageUpdated( 436 packageName, userId); 437 if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) { 438 try { 439 updateTargetPackagesLocked( 440 mImpl.onPackageChanged(packageName, userId)); 441 } catch (OperationFailedException e) { 442 Slog.e(TAG, "onPackageChanged internal error", e); 443 } 444 } 445 } 446 } 447 } finally { 448 traceEnd(TRACE_TAG_RRO); 449 } 450 } 451 onPackageReplacing(@onNull final String packageName, @NonNull final int[] userIds)452 private void onPackageReplacing(@NonNull final String packageName, 453 @NonNull final int[] userIds) { 454 try { 455 traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplacing " + packageName); 456 for (int userId : userIds) { 457 synchronized (mLock) { 458 final AndroidPackage pkg = mPackageManager.onPackageUpdated( 459 packageName, userId); 460 if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) { 461 try { 462 updateTargetPackagesLocked( 463 mImpl.onPackageReplacing(packageName, userId)); 464 } catch (OperationFailedException e) { 465 Slog.e(TAG, "onPackageReplacing internal error", e); 466 } 467 } 468 } 469 } 470 } finally { 471 traceEnd(TRACE_TAG_RRO); 472 } 473 } 474 onPackageReplaced(@onNull final String packageName, @NonNull final int[] userIds)475 private void onPackageReplaced(@NonNull final String packageName, 476 @NonNull final int[] userIds) { 477 try { 478 traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplaced " + packageName); 479 for (int userId : userIds) { 480 synchronized (mLock) { 481 final AndroidPackage pkg = mPackageManager.onPackageUpdated( 482 packageName, userId); 483 if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) { 484 try { 485 updateTargetPackagesLocked( 486 mImpl.onPackageReplaced(packageName, userId)); 487 } catch (OperationFailedException e) { 488 Slog.e(TAG, "onPackageReplaced internal error", e); 489 } 490 } 491 } 492 } 493 } finally { 494 traceEnd(TRACE_TAG_RRO); 495 } 496 } 497 onPackageRemoved(@onNull final String packageName, @NonNull final int[] userIds)498 private void onPackageRemoved(@NonNull final String packageName, 499 @NonNull final int[] userIds) { 500 try { 501 traceBegin(TRACE_TAG_RRO, "OMS#onPackageRemoved " + packageName); 502 for (int userId : userIds) { 503 synchronized (mLock) { 504 mPackageManager.onPackageRemoved(packageName, userId); 505 updateTargetPackagesLocked(mImpl.onPackageRemoved(packageName, userId)); 506 } 507 } 508 } finally { 509 traceEnd(TRACE_TAG_RRO); 510 } 511 } 512 } 513 514 private final class UserReceiver extends BroadcastReceiver { 515 @Override onReceive(@onNull final Context context, @NonNull final Intent intent)516 public void onReceive(@NonNull final Context context, @NonNull final Intent intent) { 517 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); 518 switch (intent.getAction()) { 519 case ACTION_USER_ADDED: 520 if (userId != UserHandle.USER_NULL) { 521 try { 522 traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_ADDED"); 523 synchronized (mLock) { 524 updatePackageManagerLocked(mImpl.updateOverlaysForUser(userId)); 525 } 526 } finally { 527 traceEnd(TRACE_TAG_RRO); 528 } 529 } 530 break; 531 532 case ACTION_USER_REMOVED: 533 if (userId != UserHandle.USER_NULL) { 534 try { 535 traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_REMOVED"); 536 synchronized (mLock) { 537 mImpl.onUserRemoved(userId); 538 mPackageManager.forgetAllPackageInfos(userId); 539 } 540 } finally { 541 traceEnd(TRACE_TAG_RRO); 542 } 543 } 544 break; 545 default: 546 // do nothing 547 break; 548 } 549 } 550 } 551 552 private final IBinder mService = new IOverlayManager.Stub() { 553 @Override 554 public Map<String, List<OverlayInfo>> getAllOverlays(final int userIdArg) { 555 try { 556 traceBegin(TRACE_TAG_RRO, "OMS#getAllOverlays " + userIdArg); 557 final int realUserId = handleIncomingUser(userIdArg, "getAllOverlays"); 558 559 synchronized (mLock) { 560 return mImpl.getOverlaysForUser(realUserId); 561 } 562 } finally { 563 traceEnd(TRACE_TAG_RRO); 564 } 565 } 566 567 @Override 568 public List<OverlayInfo> getOverlayInfosForTarget(@Nullable final String targetPackageName, 569 final int userIdArg) { 570 if (targetPackageName == null) { 571 return Collections.emptyList(); 572 } 573 574 try { 575 traceBegin(TRACE_TAG_RRO, "OMS#getOverlayInfosForTarget " + targetPackageName); 576 final int realUserId = handleIncomingUser(userIdArg, "getOverlayInfosForTarget"); 577 578 synchronized (mLock) { 579 return mImpl.getOverlayInfosForTarget(targetPackageName, realUserId); 580 } 581 } finally { 582 traceEnd(TRACE_TAG_RRO); 583 } 584 } 585 586 @Override 587 public OverlayInfo getOverlayInfo(@Nullable final String packageName, 588 final int userIdArg) { 589 return getOverlayInfoByIdentifier(new OverlayIdentifier(packageName), userIdArg); 590 } 591 592 @Override 593 public OverlayInfo getOverlayInfoByIdentifier(@Nullable final OverlayIdentifier overlay, 594 final int userIdArg) { 595 if (overlay == null || overlay.getPackageName() == null) { 596 return null; 597 } 598 599 try { 600 traceBegin(TRACE_TAG_RRO, "OMS#getOverlayInfo " + overlay); 601 final int realUserId = handleIncomingUser(userIdArg, "getOverlayInfo"); 602 603 synchronized (mLock) { 604 return mImpl.getOverlayInfo(overlay, realUserId); 605 } 606 } finally { 607 traceEnd(TRACE_TAG_RRO); 608 } 609 } 610 611 @Override 612 public boolean setEnabled(@Nullable final String packageName, final boolean enable, 613 int userIdArg) { 614 if (packageName == null) { 615 return false; 616 } 617 618 try { 619 traceBegin(TRACE_TAG_RRO, "OMS#setEnabled " + packageName + " " + enable); 620 621 final OverlayIdentifier overlay = new OverlayIdentifier(packageName); 622 final int realUserId = handleIncomingUser(userIdArg, "setEnabled"); 623 enforceActor(overlay, "setEnabled", realUserId); 624 625 final long ident = Binder.clearCallingIdentity(); 626 try { 627 synchronized (mLock) { 628 try { 629 updateTargetPackagesLocked( 630 mImpl.setEnabled(overlay, enable, realUserId)); 631 return true; 632 } catch (OperationFailedException e) { 633 return false; 634 } 635 } 636 } finally { 637 Binder.restoreCallingIdentity(ident); 638 } 639 } finally { 640 traceEnd(TRACE_TAG_RRO); 641 } 642 } 643 644 @Override 645 public boolean setEnabledExclusive(@Nullable final String packageName, final boolean enable, 646 int userIdArg) { 647 if (packageName == null || !enable) { 648 return false; 649 } 650 651 try { 652 traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusive " + packageName + " " + enable); 653 654 final OverlayIdentifier overlay = new OverlayIdentifier(packageName); 655 final int realUserId = handleIncomingUser(userIdArg, "setEnabledExclusive"); 656 enforceActor(overlay, "setEnabledExclusive", realUserId); 657 658 final long ident = Binder.clearCallingIdentity(); 659 try { 660 synchronized (mLock) { 661 try { 662 mImpl.setEnabledExclusive( 663 overlay, false /* withinCategory */, realUserId) 664 .ifPresent( 665 OverlayManagerService.this::updateTargetPackagesLocked); 666 return true; 667 } catch (OperationFailedException e) { 668 return false; 669 } 670 } 671 } finally { 672 Binder.restoreCallingIdentity(ident); 673 } 674 } finally { 675 traceEnd(TRACE_TAG_RRO); 676 } 677 } 678 679 @Override 680 public boolean setEnabledExclusiveInCategory(@Nullable String packageName, 681 final int userIdArg) { 682 if (packageName == null) { 683 return false; 684 } 685 686 try { 687 traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusiveInCategory " + packageName); 688 689 final OverlayIdentifier overlay = new OverlayIdentifier(packageName); 690 final int realUserId = handleIncomingUser(userIdArg, 691 "setEnabledExclusiveInCategory"); 692 enforceActor(overlay, "setEnabledExclusiveInCategory", realUserId); 693 694 final long ident = Binder.clearCallingIdentity(); 695 try { 696 synchronized (mLock) { 697 try { 698 mImpl.setEnabledExclusive(overlay, 699 true /* withinCategory */, realUserId) 700 .ifPresent(OverlayManagerService.this::updateTargetPackagesLocked); 701 return true; 702 } catch (OperationFailedException e) { 703 return false; 704 } 705 } 706 } finally { 707 Binder.restoreCallingIdentity(ident); 708 } 709 } finally { 710 traceEnd(TRACE_TAG_RRO); 711 } 712 } 713 714 @Override 715 public boolean setPriority(@Nullable final String packageName, 716 @Nullable final String parentPackageName, final int userIdArg) { 717 if (packageName == null || parentPackageName == null) { 718 return false; 719 } 720 721 try { 722 traceBegin(TRACE_TAG_RRO, "OMS#setPriority " + packageName + " " 723 + parentPackageName); 724 725 final OverlayIdentifier overlay = new OverlayIdentifier(packageName); 726 final OverlayIdentifier parentOverlay = new OverlayIdentifier(parentPackageName); 727 final int realUserId = handleIncomingUser(userIdArg, "setPriority"); 728 enforceActor(overlay, "setPriority", realUserId); 729 730 final long ident = Binder.clearCallingIdentity(); 731 try { 732 synchronized (mLock) { 733 try { 734 mImpl.setPriority(overlay, parentOverlay, realUserId) 735 .ifPresent(OverlayManagerService.this::updateTargetPackagesLocked); 736 return true; 737 } catch (OperationFailedException e) { 738 return false; 739 } 740 } 741 } finally { 742 Binder.restoreCallingIdentity(ident); 743 } 744 } finally { 745 traceEnd(TRACE_TAG_RRO); 746 } 747 } 748 749 @Override 750 public boolean setHighestPriority(@Nullable final String packageName, final int userIdArg) { 751 if (packageName == null) { 752 return false; 753 } 754 755 try { 756 traceBegin(TRACE_TAG_RRO, "OMS#setHighestPriority " + packageName); 757 758 final OverlayIdentifier overlay = new OverlayIdentifier(packageName); 759 final int realUserId = handleIncomingUser(userIdArg, "setHighestPriority"); 760 enforceActor(overlay, "setHighestPriority", realUserId); 761 762 final long ident = Binder.clearCallingIdentity(); 763 try { 764 synchronized (mLock) { 765 try { 766 updateTargetPackagesLocked( 767 mImpl.setHighestPriority(overlay, realUserId)); 768 return true; 769 } catch (OperationFailedException e) { 770 return false; 771 } 772 } 773 } finally { 774 Binder.restoreCallingIdentity(ident); 775 } 776 } finally { 777 traceEnd(TRACE_TAG_RRO); 778 } 779 } 780 781 @Override 782 public boolean setLowestPriority(@Nullable final String packageName, final int userIdArg) { 783 if (packageName == null) { 784 return false; 785 } 786 787 try { 788 traceBegin(TRACE_TAG_RRO, "OMS#setLowestPriority " + packageName); 789 790 final OverlayIdentifier overlay = new OverlayIdentifier(packageName); 791 final int realUserId = handleIncomingUser(userIdArg, "setLowestPriority"); 792 enforceActor(overlay, "setLowestPriority", realUserId); 793 794 final long ident = Binder.clearCallingIdentity(); 795 try { 796 synchronized (mLock) { 797 try { 798 mImpl.setLowestPriority(overlay, realUserId) 799 .ifPresent(OverlayManagerService.this::updateTargetPackagesLocked); 800 return true; 801 } catch (OperationFailedException e) { 802 return false; 803 } 804 } 805 } finally { 806 Binder.restoreCallingIdentity(ident); 807 } 808 } finally { 809 traceEnd(TRACE_TAG_RRO); 810 } 811 } 812 813 @Override 814 public String[] getDefaultOverlayPackages() { 815 try { 816 traceBegin(TRACE_TAG_RRO, "OMS#getDefaultOverlayPackages"); 817 getContext().enforceCallingOrSelfPermission( 818 android.Manifest.permission.MODIFY_THEME_OVERLAY, null); 819 820 final long ident = Binder.clearCallingIdentity(); 821 try { 822 synchronized (mLock) { 823 return mImpl.getDefaultOverlayPackages(); 824 } 825 } finally { 826 Binder.restoreCallingIdentity(ident); 827 } 828 } finally { 829 traceEnd(TRACE_TAG_RRO); 830 } 831 } 832 833 @Override 834 public void invalidateCachesForOverlay(@Nullable String packageName, final int userIdArg) { 835 if (packageName == null) { 836 return; 837 } 838 839 final OverlayIdentifier overlay = new OverlayIdentifier(packageName); 840 final int realUserId = handleIncomingUser(userIdArg, "invalidateCachesForOverlay"); 841 enforceActor(overlay, "invalidateCachesForOverlay", realUserId); 842 final long ident = Binder.clearCallingIdentity(); 843 try { 844 synchronized (mLock) { 845 try { 846 mImpl.removeIdmapForOverlay(overlay, realUserId); 847 } catch (OperationFailedException e) { 848 Slog.w(TAG, "invalidate caches for overlay '" + overlay + "' failed", e); 849 } 850 } 851 } finally { 852 Binder.restoreCallingIdentity(ident); 853 } 854 } 855 856 @Override 857 public void commit(@NonNull final OverlayManagerTransaction transaction) 858 throws RemoteException { 859 try { 860 traceBegin(TRACE_TAG_RRO, "OMS#commit " + transaction); 861 try { 862 executeAllRequests(transaction); 863 } catch (Exception e) { 864 final long ident = Binder.clearCallingIdentity(); 865 try { 866 restoreSettings(); 867 } finally { 868 Binder.restoreCallingIdentity(ident); 869 } 870 Slog.d(TAG, "commit failed: " + e.getMessage(), e); 871 throw new SecurityException("commit failed" 872 + (DEBUG ? ": " + e.getMessage() : "")); 873 } 874 } finally { 875 traceEnd(TRACE_TAG_RRO); 876 } 877 } 878 879 private Set<PackageAndUser> executeRequest( 880 @NonNull final OverlayManagerTransaction.Request request) 881 throws OperationFailedException { 882 Objects.requireNonNull(request, "Transaction contains a null request"); 883 Objects.requireNonNull(request.overlay, 884 "Transaction overlay identifier must be non-null"); 885 886 final int callingUid = Binder.getCallingUid(); 887 final int realUserId; 888 if (request.type == TYPE_REGISTER_FABRICATED 889 || request.type == TYPE_UNREGISTER_FABRICATED) { 890 if (request.userId != UserHandle.USER_ALL) { 891 throw new IllegalArgumentException(request.typeToString() 892 + " unsupported for user " + request.userId); 893 } 894 realUserId = UserHandle.USER_ALL; 895 896 // Enforce that the calling process can only register and unregister fabricated 897 // overlays using its package name. 898 final String pkgName = request.overlay.getPackageName(); 899 if (callingUid != Process.ROOT_UID && !ArrayUtils.contains( 900 mPackageManager.getPackagesForUid(callingUid), pkgName)) { 901 throw new IllegalArgumentException("UID " + callingUid + " does own package" 902 + "name " + pkgName); 903 } 904 } else { 905 // Enforce actor requirements for enabling, disabling, and reordering overlays. 906 realUserId = handleIncomingUser(request.userId, request.typeToString()); 907 enforceActor(request.overlay, request.typeToString(), realUserId); 908 } 909 910 final long ident = Binder.clearCallingIdentity(); 911 try { 912 switch (request.type) { 913 case TYPE_SET_ENABLED: 914 Set<PackageAndUser> result = null; 915 result = CollectionUtils.addAll(result, 916 mImpl.setEnabled(request.overlay, true, realUserId)); 917 result = CollectionUtils.addAll(result, 918 mImpl.setHighestPriority(request.overlay, realUserId)); 919 return CollectionUtils.emptyIfNull(result); 920 921 case TYPE_SET_DISABLED: 922 return mImpl.setEnabled(request.overlay, false, realUserId); 923 924 case TYPE_REGISTER_FABRICATED: 925 final FabricatedOverlayInternal fabricated = 926 request.extras.getParcelable( 927 OverlayManagerTransaction.Request.BUNDLE_FABRICATED_OVERLAY 928 ); 929 Objects.requireNonNull(fabricated, 930 "no fabricated overlay attached to request"); 931 return mImpl.registerFabricatedOverlay(fabricated); 932 933 case TYPE_UNREGISTER_FABRICATED: 934 return mImpl.unregisterFabricatedOverlay(request.overlay); 935 936 default: 937 throw new IllegalArgumentException("unsupported request: " + request); 938 } 939 } finally { 940 Binder.restoreCallingIdentity(ident); 941 } 942 } 943 944 private void executeAllRequests(@NonNull final OverlayManagerTransaction transaction) 945 throws OperationFailedException { 946 if (DEBUG) { 947 Slog.d(TAG, "commit " + transaction); 948 } 949 if (transaction == null) { 950 throw new IllegalArgumentException("null transaction"); 951 } 952 953 synchronized (mLock) { 954 // execute the requests (as calling user) 955 Set<PackageAndUser> affectedPackagesToUpdate = null; 956 for (final OverlayManagerTransaction.Request request : transaction) { 957 affectedPackagesToUpdate = CollectionUtils.addAll(affectedPackagesToUpdate, 958 executeRequest(request)); 959 } 960 961 // past the point of no return: the entire transaction has been 962 // processed successfully, we can no longer fail: continue as 963 // system_server 964 final long ident = Binder.clearCallingIdentity(); 965 try { 966 updateTargetPackagesLocked(affectedPackagesToUpdate); 967 } finally { 968 Binder.restoreCallingIdentity(ident); 969 } 970 } 971 } 972 973 @Override 974 public void onShellCommand(@NonNull final FileDescriptor in, 975 @NonNull final FileDescriptor out, @NonNull final FileDescriptor err, 976 @NonNull final String[] args, @NonNull final ShellCallback callback, 977 @NonNull final ResultReceiver resultReceiver) { 978 (new OverlayManagerShellCommand(getContext(), this)).exec( 979 this, in, out, err, args, callback, resultReceiver); 980 } 981 982 @Override 983 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 984 final DumpState dumpState = new DumpState(); 985 dumpState.setUserId(UserHandle.USER_ALL); 986 987 int opti = 0; 988 while (opti < args.length) { 989 final String opt = args[opti]; 990 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 991 break; 992 } 993 opti++; 994 995 if ("-h".equals(opt)) { 996 pw.println("dump [-h] [--verbose] [--user USER_ID] [[FIELD] PACKAGE]"); 997 pw.println(" Print debugging information about the overlay manager."); 998 pw.println(" With optional parameter PACKAGE, limit output to the specified"); 999 pw.println(" package. With optional parameter FIELD, limit output to"); 1000 pw.println(" the value of that SettingsItem field. Field names are"); 1001 pw.println(" case insensitive and out.println the m prefix can be omitted,"); 1002 pw.println(" so the following are equivalent: mState, mstate, State, state."); 1003 return; 1004 } else if ("--user".equals(opt)) { 1005 if (opti >= args.length) { 1006 pw.println("Error: user missing argument"); 1007 return; 1008 } 1009 try { 1010 dumpState.setUserId(Integer.parseInt(args[opti])); 1011 opti++; 1012 } catch (NumberFormatException e) { 1013 pw.println("Error: user argument is not a number: " + args[opti]); 1014 return; 1015 } 1016 } else if ("--verbose".equals(opt)) { 1017 dumpState.setVerbose(true); 1018 } else { 1019 pw.println("Unknown argument: " + opt + "; use -h for help"); 1020 } 1021 } 1022 if (opti < args.length) { 1023 final String arg = args[opti]; 1024 opti++; 1025 switch (arg) { 1026 case "packagename": 1027 case "userid": 1028 case "targetpackagename": 1029 case "targetoverlayablename": 1030 case "basecodepath": 1031 case "state": 1032 case "isenabled": 1033 case "ismutable": 1034 case "priority": 1035 case "category": 1036 dumpState.setField(arg); 1037 break; 1038 default: 1039 dumpState.setOverlyIdentifier(arg); 1040 break; 1041 } 1042 } 1043 if (dumpState.getPackageName() == null && opti < args.length) { 1044 dumpState.setOverlyIdentifier(args[opti]); 1045 opti++; 1046 } 1047 1048 enforceDumpPermission("dump"); 1049 synchronized (mLock) { 1050 mImpl.dump(pw, dumpState); 1051 if (dumpState.getPackageName() == null) { 1052 mPackageManager.dump(pw, dumpState); 1053 } 1054 } 1055 } 1056 1057 /** 1058 * Ensure that the caller has permission to interact with the given userId. 1059 * If the calling user is not the same as the provided user, the caller needs 1060 * to hold the INTERACT_ACROSS_USERS_FULL permission (or be system uid or 1061 * root). 1062 * 1063 * @param userId the user to interact with 1064 * @param message message for any SecurityException 1065 */ 1066 private int handleIncomingUser(final int userId, @NonNull final String message) { 1067 return ActivityManager.handleIncomingUser(Binder.getCallingPid(), 1068 Binder.getCallingUid(), userId, false, true, message, null); 1069 } 1070 1071 /** 1072 * Enforce that the caller holds the DUMP permission (or is system or root). 1073 * 1074 * @param message used as message if SecurityException is thrown 1075 * @throws SecurityException if the permission check fails 1076 */ 1077 private void enforceDumpPermission(@NonNull final String message) { 1078 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, message); 1079 } 1080 1081 private void enforceActor(@NonNull OverlayIdentifier overlay, @NonNull String methodName, 1082 int realUserId) throws SecurityException { 1083 OverlayInfo overlayInfo = mImpl.getOverlayInfo(overlay, realUserId); 1084 if (overlayInfo == null) { 1085 throw new IllegalArgumentException("Unable to retrieve overlay information for " 1086 + overlay); 1087 } 1088 1089 int callingUid = Binder.getCallingUid(); 1090 mActorEnforcer.enforceActor(overlayInfo, methodName, callingUid, realUserId); 1091 } 1092 }; 1093 1094 private static final class PackageManagerHelperImpl implements PackageManagerHelper { 1095 private static class AndroidPackageUsers { 1096 private AndroidPackage mPackage; 1097 private final Set<Integer> mInstalledUsers = new ArraySet<>(); AndroidPackageUsers(@onNull AndroidPackage pkg)1098 private AndroidPackageUsers(@NonNull AndroidPackage pkg) { 1099 this.mPackage = pkg; 1100 } 1101 } 1102 private final Context mContext; 1103 private final IPackageManager mPackageManager; 1104 private final PackageManagerInternal mPackageManagerInternal; 1105 1106 // Use a cache for performance and for consistency within OMS: because 1107 // additional PACKAGE_* intents may be delivered while we process an 1108 // intent, querying the PackageManagerService for the actual current 1109 // state may lead to contradictions within OMS. Better then to lag 1110 // behind until all pending intents have been processed. 1111 private final ArrayMap<String, AndroidPackageUsers> mCache = new ArrayMap<>(); 1112 private final Set<Integer> mInitializedUsers = new ArraySet<>(); 1113 PackageManagerHelperImpl(Context context)1114 PackageManagerHelperImpl(Context context) { 1115 mContext = context; 1116 mPackageManager = getPackageManager(); 1117 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); 1118 } 1119 1120 /** 1121 * Initializes the helper for the user. This only needs to be invoked one time before 1122 * packages of this user are queried. 1123 * @param userId the user id to initialize 1124 * @return a map of package name to all packages installed in the user 1125 */ 1126 @NonNull initializeForUser(final int userId)1127 public ArrayMap<String, AndroidPackage> initializeForUser(final int userId) { 1128 if (!mInitializedUsers.contains(userId)) { 1129 mInitializedUsers.add(userId); 1130 mPackageManagerInternal.forEachInstalledPackage( 1131 (pkg) -> addPackageUser(pkg, userId), userId); 1132 } 1133 1134 final ArrayMap<String, AndroidPackage> userPackages = new ArrayMap<>(); 1135 for (int i = 0, n = mCache.size(); i < n; i++) { 1136 final AndroidPackageUsers pkg = mCache.valueAt(i); 1137 if (pkg.mInstalledUsers.contains(userId)) { 1138 userPackages.put(mCache.keyAt(i), pkg.mPackage); 1139 } 1140 } 1141 return userPackages; 1142 } 1143 1144 @Override 1145 @Nullable getPackageForUser(@onNull final String packageName, final int userId)1146 public AndroidPackage getPackageForUser(@NonNull final String packageName, 1147 final int userId) { 1148 final AndroidPackageUsers pkg = mCache.get(packageName); 1149 if (pkg != null && pkg.mInstalledUsers.contains(userId)) { 1150 return pkg.mPackage; 1151 } 1152 try { 1153 if (!mPackageManager.isPackageAvailable(packageName, userId)) { 1154 return null; 1155 } 1156 } catch (RemoteException e) { 1157 Slog.w(TAG, "Failed to check availability of package '" + packageName 1158 + "' for user " + userId, e); 1159 return null; 1160 } 1161 return addPackageUser(packageName, userId); 1162 } 1163 1164 @NonNull addPackageUser(@onNull final String packageName, final int user)1165 private AndroidPackage addPackageUser(@NonNull final String packageName, 1166 final int user) { 1167 final AndroidPackage pkg = mPackageManagerInternal.getPackage(packageName); 1168 if (pkg == null) { 1169 Slog.w(TAG, "Android package for '" + packageName + "' could not be found;" 1170 + " continuing as if package was never added", new Throwable()); 1171 return null; 1172 } 1173 return addPackageUser(pkg, user); 1174 } 1175 1176 @NonNull addPackageUser(@onNull final AndroidPackage pkg, final int user)1177 private AndroidPackage addPackageUser(@NonNull final AndroidPackage pkg, 1178 final int user) { 1179 AndroidPackageUsers pkgUsers = mCache.get(pkg.getPackageName()); 1180 if (pkgUsers == null) { 1181 pkgUsers = new AndroidPackageUsers(pkg); 1182 mCache.put(pkg.getPackageName(), pkgUsers); 1183 } else { 1184 pkgUsers.mPackage = pkg; 1185 } 1186 pkgUsers.mInstalledUsers.add(user); 1187 return pkgUsers.mPackage; 1188 } 1189 1190 1191 @NonNull removePackageUser(@onNull final String packageName, final int user)1192 private void removePackageUser(@NonNull final String packageName, final int user) { 1193 final AndroidPackageUsers pkgUsers = mCache.get(packageName); 1194 if (pkgUsers == null) { 1195 return; 1196 } 1197 removePackageUser(pkgUsers, user); 1198 } 1199 1200 @NonNull removePackageUser(@onNull final AndroidPackageUsers pkg, final int user)1201 private void removePackageUser(@NonNull final AndroidPackageUsers pkg, final int user) { 1202 pkg.mInstalledUsers.remove(user); 1203 if (pkg.mInstalledUsers.isEmpty()) { 1204 mCache.remove(pkg.mPackage.getPackageName()); 1205 } 1206 } 1207 1208 @Nullable onPackageAdded(@onNull final String packageName, final int userId)1209 public AndroidPackage onPackageAdded(@NonNull final String packageName, final int userId) { 1210 return addPackageUser(packageName, userId); 1211 } 1212 1213 @Nullable onPackageUpdated(@onNull final String packageName, final int userId)1214 public AndroidPackage onPackageUpdated(@NonNull final String packageName, 1215 final int userId) { 1216 return addPackageUser(packageName, userId); 1217 } 1218 onPackageRemoved(@onNull final String packageName, final int userId)1219 public void onPackageRemoved(@NonNull final String packageName, final int userId) { 1220 removePackageUser(packageName, userId); 1221 } 1222 1223 @Override isInstantApp(@onNull final String packageName, final int userId)1224 public boolean isInstantApp(@NonNull final String packageName, final int userId) { 1225 return mPackageManagerInternal.isInstantApp(packageName, userId); 1226 } 1227 1228 @NonNull 1229 @Override getNamedActors()1230 public Map<String, Map<String, String>> getNamedActors() { 1231 return SystemConfig.getInstance().getNamedActors(); 1232 } 1233 1234 @Override signaturesMatching(@onNull final String packageName1, @NonNull final String packageName2, final int userId)1235 public boolean signaturesMatching(@NonNull final String packageName1, 1236 @NonNull final String packageName2, final int userId) { 1237 // The package manager does not support different versions of packages 1238 // to be installed for different users: ignore userId for now. 1239 try { 1240 return mPackageManager.checkSignatures( 1241 packageName1, packageName2) == SIGNATURE_MATCH; 1242 } catch (RemoteException e) { 1243 // Intentionally left blank 1244 } 1245 return false; 1246 } 1247 1248 @Override getConfigSignaturePackage()1249 public String getConfigSignaturePackage() { 1250 final String[] pkgs = mPackageManagerInternal.getKnownPackageNames( 1251 PackageManagerInternal.PACKAGE_OVERLAY_CONFIG_SIGNATURE, 1252 UserHandle.USER_SYSTEM); 1253 return (pkgs.length == 0) ? null : pkgs[0]; 1254 } 1255 1256 @Nullable 1257 @Override getOverlayableForTarget(@onNull String packageName, @NonNull String targetOverlayableName, int userId)1258 public OverlayableInfo getOverlayableForTarget(@NonNull String packageName, 1259 @NonNull String targetOverlayableName, int userId) 1260 throws IOException { 1261 final AndroidPackage packageInfo = getPackageForUser(packageName, userId); 1262 if (packageInfo == null) { 1263 throw new IOException("Unable to get target package"); 1264 } 1265 1266 ApkAssets apkAssets = null; 1267 try { 1268 apkAssets = ApkAssets.loadFromPath(packageInfo.getBaseApkPath()); 1269 return apkAssets.getOverlayableInfo(targetOverlayableName); 1270 } finally { 1271 if (apkAssets != null) { 1272 try { 1273 apkAssets.close(); 1274 } catch (Throwable ignored) { 1275 } 1276 } 1277 } 1278 } 1279 1280 @Override doesTargetDefineOverlayable(String targetPackageName, int userId)1281 public boolean doesTargetDefineOverlayable(String targetPackageName, int userId) 1282 throws IOException { 1283 AndroidPackage packageInfo = getPackageForUser(targetPackageName, userId); 1284 if (packageInfo == null) { 1285 throw new IOException("Unable to get target package"); 1286 } 1287 1288 ApkAssets apkAssets = null; 1289 try { 1290 apkAssets = ApkAssets.loadFromPath(packageInfo.getBaseApkPath()); 1291 return apkAssets.definesOverlayable(); 1292 } finally { 1293 if (apkAssets != null) { 1294 try { 1295 apkAssets.close(); 1296 } catch (Throwable ignored) { 1297 } 1298 } 1299 } 1300 } 1301 1302 @Override enforcePermission(String permission, String message)1303 public void enforcePermission(String permission, String message) throws SecurityException { 1304 mContext.enforceCallingOrSelfPermission(permission, message); 1305 } 1306 forgetAllPackageInfos(final int userId)1307 public void forgetAllPackageInfos(final int userId) { 1308 // Iterate in reverse order since removing the package in all users will remove the 1309 // package from the cache. 1310 for (int i = mCache.size() - 1; i >= 0; i--) { 1311 removePackageUser(mCache.valueAt(i), userId); 1312 } 1313 } 1314 1315 @Nullable 1316 @Override getPackagesForUid(int uid)1317 public String[] getPackagesForUid(int uid) { 1318 try { 1319 return mPackageManager.getPackagesForUid(uid); 1320 } catch (RemoteException ignored) { 1321 return null; 1322 } 1323 } 1324 1325 private static final String TAB1 = " "; 1326 dump(@onNull final PrintWriter pw, @NonNull DumpState dumpState)1327 public void dump(@NonNull final PrintWriter pw, @NonNull DumpState dumpState) { 1328 pw.println("AndroidPackage cache"); 1329 1330 if (!dumpState.isVerbose()) { 1331 pw.println(TAB1 + mCache.size() + " package(s)"); 1332 return; 1333 } 1334 1335 if (mCache.size() == 0) { 1336 pw.println(TAB1 + "<empty>"); 1337 return; 1338 } 1339 1340 for (int i = 0, n = mCache.size(); i < n; i++) { 1341 final String packageName = mCache.keyAt(i); 1342 final AndroidPackageUsers pkg = mCache.valueAt(i); 1343 pw.print(TAB1 + packageName + ": " + pkg.mPackage + " users="); 1344 pw.println(TextUtils.join(", ", pkg.mInstalledUsers)); 1345 } 1346 } 1347 } 1348 updateTargetPackagesLocked(@ullable PackageAndUser updatedTarget)1349 private void updateTargetPackagesLocked(@Nullable PackageAndUser updatedTarget) { 1350 if (updatedTarget != null) { 1351 updateTargetPackagesLocked(Set.of(updatedTarget)); 1352 } 1353 } 1354 updateTargetPackagesLocked(@ullable Set<PackageAndUser> updatedTargets)1355 private void updateTargetPackagesLocked(@Nullable Set<PackageAndUser> updatedTargets) { 1356 if (CollectionUtils.isEmpty(updatedTargets)) { 1357 return; 1358 } 1359 persistSettingsLocked(); 1360 final SparseArray<ArraySet<String>> userTargets = groupTargetsByUserId(updatedTargets); 1361 for (int i = 0, n = userTargets.size(); i < n; i++) { 1362 final ArraySet<String> targets = userTargets.valueAt(i); 1363 final int userId = userTargets.keyAt(i); 1364 final List<String> affectedPackages = updatePackageManagerLocked(targets, userId); 1365 if (affectedPackages.isEmpty()) { 1366 // The package manager paths are already up-to-date. 1367 continue; 1368 } 1369 1370 FgThread.getHandler().post(() -> { 1371 // Send configuration changed events for all target packages that have been affected 1372 // by overlay state changes. 1373 updateActivityManager(affectedPackages, userId); 1374 1375 // Do not send broadcasts for all affected targets. Overlays targeting the framework 1376 // or shared libraries may cause too many broadcasts to be sent at once. 1377 broadcastActionOverlayChanged(targets, userId); 1378 }); 1379 } 1380 } 1381 1382 @Nullable groupTargetsByUserId( @ullable final Set<PackageAndUser> targetsAndUsers)1383 private static SparseArray<ArraySet<String>> groupTargetsByUserId( 1384 @Nullable final Set<PackageAndUser> targetsAndUsers) { 1385 final SparseArray<ArraySet<String>> userTargets = new SparseArray<>(); 1386 CollectionUtils.forEach(targetsAndUsers, target -> { 1387 ArraySet<String> targets = userTargets.get(target.userId); 1388 if (targets == null) { 1389 targets = new ArraySet<>(); 1390 userTargets.put(target.userId, targets); 1391 } 1392 targets.add(target.packageName); 1393 }); 1394 return userTargets; 1395 } 1396 1397 // Helper methods to update other parts of the system or read/write 1398 // settings: these methods should never call into each other! 1399 broadcastActionOverlayChanged(@onNull final Set<String> targetPackages, final int userId)1400 private static void broadcastActionOverlayChanged(@NonNull final Set<String> targetPackages, 1401 final int userId) { 1402 CollectionUtils.forEach(targetPackages, target -> { 1403 final Intent intent = new Intent(ACTION_OVERLAY_CHANGED, 1404 Uri.fromParts("package", target, null)); 1405 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1406 try { 1407 ActivityManager.getService().broadcastIntent(null, intent, null, null, 0, null, 1408 null, null, android.app.AppOpsManager.OP_NONE, null, false, false, userId); 1409 } catch (RemoteException e) { 1410 Slog.e(TAG, "broadcastActionOverlayChanged remote exception", e); 1411 } 1412 }); 1413 } 1414 1415 /** 1416 * Tell the activity manager to tell a set of packages to reload their 1417 * resources. 1418 */ updateActivityManager(@onNull List<String> targetPackageNames, final int userId)1419 private void updateActivityManager(@NonNull List<String> targetPackageNames, final int userId) { 1420 final IActivityManager am = ActivityManager.getService(); 1421 try { 1422 am.scheduleApplicationInfoChanged(targetPackageNames, userId); 1423 } catch (RemoteException e) { 1424 Slog.e(TAG, "updateActivityManager remote exception", e); 1425 } 1426 } 1427 1428 @NonNull updatePackageManagerLocked( @ullable Set<PackageAndUser> targets)1429 private SparseArray<List<String>> updatePackageManagerLocked( 1430 @Nullable Set<PackageAndUser> targets) { 1431 if (CollectionUtils.isEmpty(targets)) { 1432 return new SparseArray<>(); 1433 } 1434 final SparseArray<List<String>> affectedTargets = new SparseArray<>(); 1435 final SparseArray<ArraySet<String>> userTargets = groupTargetsByUserId(targets); 1436 for (int i = 0, n = userTargets.size(); i < n; i++) { 1437 final int userId = userTargets.keyAt(i); 1438 affectedTargets.put(userId, updatePackageManagerLocked(userTargets.valueAt(i), userId)); 1439 } 1440 return affectedTargets; 1441 } 1442 1443 /** 1444 * Updates the target packages' set of enabled overlays in PackageManager. 1445 * @return the package names of affected targets (a superset of 1446 * targetPackageNames: the target themselves and shared libraries) 1447 */ 1448 @NonNull updatePackageManagerLocked(@onNull Collection<String> targetPackageNames, final int userId)1449 private List<String> updatePackageManagerLocked(@NonNull Collection<String> targetPackageNames, 1450 final int userId) { 1451 try { 1452 traceBegin(TRACE_TAG_RRO, "OMS#updatePackageManagerLocked " + targetPackageNames); 1453 if (DEBUG) { 1454 Slog.d(TAG, "Update package manager about changed overlays"); 1455 } 1456 final PackageManagerInternal pm = 1457 LocalServices.getService(PackageManagerInternal.class); 1458 final boolean updateFrameworkRes = targetPackageNames.contains("android"); 1459 if (updateFrameworkRes) { 1460 targetPackageNames = pm.getTargetPackageNames(userId); 1461 } 1462 1463 final Map<String, OverlayPaths> pendingChanges = 1464 new ArrayMap<>(targetPackageNames.size()); 1465 synchronized (mLock) { 1466 final OverlayPaths frameworkOverlays = 1467 mImpl.getEnabledOverlayPaths("android", userId); 1468 for (final String targetPackageName : targetPackageNames) { 1469 final OverlayPaths.Builder list = new OverlayPaths.Builder(); 1470 if (!"android".equals(targetPackageName)) { 1471 list.addAll(frameworkOverlays); 1472 } 1473 list.addAll(mImpl.getEnabledOverlayPaths(targetPackageName, userId)); 1474 pendingChanges.put(targetPackageName, list.build()); 1475 } 1476 } 1477 1478 final HashSet<String> updatedPackages = new HashSet<>(); 1479 for (final String targetPackageName : targetPackageNames) { 1480 if (DEBUG) { 1481 Slog.d(TAG, "-> Updating overlay: target=" + targetPackageName + " overlays=[" 1482 + pendingChanges.get(targetPackageName) 1483 + "] userId=" + userId); 1484 } 1485 1486 if (!pm.setEnabledOverlayPackages( 1487 userId, targetPackageName, pendingChanges.get(targetPackageName), 1488 updatedPackages)) { 1489 Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d", 1490 targetPackageName, userId)); 1491 } 1492 } 1493 return new ArrayList<>(updatedPackages); 1494 } finally { 1495 traceEnd(TRACE_TAG_RRO); 1496 } 1497 } 1498 persistSettingsLocked()1499 private void persistSettingsLocked() { 1500 if (DEBUG) { 1501 Slog.d(TAG, "Writing overlay settings"); 1502 } 1503 FileOutputStream stream = null; 1504 try { 1505 stream = mSettingsFile.startWrite(); 1506 mSettings.persist(stream); 1507 mSettingsFile.finishWrite(stream); 1508 } catch (IOException | XmlPullParserException e) { 1509 mSettingsFile.failWrite(stream); 1510 Slog.e(TAG, "failed to persist overlay state", e); 1511 } 1512 } 1513 restoreSettings()1514 private void restoreSettings() { 1515 try { 1516 traceBegin(TRACE_TAG_RRO, "OMS#restoreSettings"); 1517 synchronized (mLock) { 1518 if (!mSettingsFile.getBaseFile().exists()) { 1519 return; 1520 } 1521 try (FileInputStream stream = mSettingsFile.openRead()) { 1522 mSettings.restore(stream); 1523 1524 // We might have data for dying users if the device was 1525 // restarted before we received USER_REMOVED. Remove data for 1526 // users that will not exist after the system is ready. 1527 1528 final List<UserInfo> liveUsers = mUserManager.getUsers(true /*excludeDying*/); 1529 final int[] liveUserIds = new int[liveUsers.size()]; 1530 for (int i = 0; i < liveUsers.size(); i++) { 1531 liveUserIds[i] = liveUsers.get(i).getUserHandle().getIdentifier(); 1532 } 1533 Arrays.sort(liveUserIds); 1534 1535 for (int userId : mSettings.getUsers()) { 1536 if (Arrays.binarySearch(liveUserIds, userId) < 0) { 1537 mSettings.removeUser(userId); 1538 } 1539 } 1540 } catch (IOException | XmlPullParserException e) { 1541 Slog.e(TAG, "failed to restore overlay state", e); 1542 } 1543 } 1544 } finally { 1545 traceEnd(TRACE_TAG_RRO); 1546 } 1547 } 1548 } 1549