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_PACKAGE_ADDED; 21 import static android.content.Intent.ACTION_PACKAGE_CHANGED; 22 import static android.content.Intent.ACTION_PACKAGE_REMOVED; 23 import static android.content.Intent.ACTION_USER_ADDED; 24 import static android.content.Intent.ACTION_USER_REMOVED; 25 import static android.content.pm.PackageManager.SIGNATURE_MATCH; 26 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.app.ActivityManager; 30 import android.app.IActivityManager; 31 import android.content.BroadcastReceiver; 32 import android.content.Context; 33 import android.content.Intent; 34 import android.content.IntentFilter; 35 import android.content.om.IOverlayManager; 36 import android.content.om.OverlayInfo; 37 import android.content.pm.IPackageManager; 38 import android.content.pm.PackageInfo; 39 import android.content.pm.PackageManagerInternal; 40 import android.content.pm.UserInfo; 41 import android.net.Uri; 42 import android.os.Binder; 43 import android.os.Environment; 44 import android.os.IBinder; 45 import android.os.RemoteException; 46 import android.os.ResultReceiver; 47 import android.os.ShellCallback; 48 import android.os.SystemProperties; 49 import android.os.UserHandle; 50 import android.os.UserManager; 51 import android.text.TextUtils; 52 import android.util.ArrayMap; 53 import android.util.ArraySet; 54 import android.util.AtomicFile; 55 import android.util.Slog; 56 import android.util.SparseArray; 57 58 import com.android.internal.util.ConcurrentUtils; 59 import com.android.server.FgThread; 60 import com.android.server.IoThread; 61 import com.android.server.LocalServices; 62 import com.android.server.SystemServerInitThreadPool; 63 import com.android.server.SystemService; 64 import com.android.server.pm.Installer; 65 import com.android.server.pm.UserManagerService; 66 67 import org.xmlpull.v1.XmlPullParserException; 68 69 import java.io.File; 70 import java.io.FileDescriptor; 71 import java.io.FileInputStream; 72 import java.io.FileOutputStream; 73 import java.io.IOException; 74 import java.io.PrintWriter; 75 import java.util.ArrayList; 76 import java.util.Arrays; 77 import java.util.Collections; 78 import java.util.HashMap; 79 import java.util.List; 80 import java.util.Map; 81 import java.util.Set; 82 import java.util.concurrent.Future; 83 import java.util.concurrent.atomic.AtomicBoolean; 84 85 /** 86 * Service to manage asset overlays. 87 * 88 * <p>Asset overlays are additional resources that come from apks loaded 89 * alongside the system and app apks. This service, the OverlayManagerService 90 * (OMS), tracks which installed overlays to use and provides methods to change 91 * this. Changes propagate to running applications as part of the Activity 92 * lifecycle. This allows Activities to reread their resources at a well 93 * defined point.</p> 94 * 95 * <p>By itself, the OMS will not change what overlays should be active. 96 * Instead, it is only responsible for making sure that overlays *can* be used 97 * from a technical and security point of view and to activate overlays in 98 * response to external requests. The responsibility to toggle overlays on and 99 * off lies within components that implement different use-cases such as themes 100 * or dynamic customization.</p> 101 * 102 * <p>The OMS receives input from three sources:</p> 103 * 104 * <ul> 105 * <li>Callbacks from the SystemService class, specifically when the 106 * Android framework is booting and when the end user switches Android 107 * users.</li> 108 * 109 * <li>Intents from the PackageManagerService (PMS). Overlays are regular 110 * apks, and whenever a package is installed (or removed, or has a 111 * component enabled or disabled), the PMS broadcasts this as an intent. 112 * When the OMS receives one of these intents, it updates its internal 113 * representation of the available overlays and, if there was a visible 114 * change, triggers an asset refresh in the affected apps.</li> 115 * 116 * <li>External requests via the {@link IOverlayManager AIDL interface}. 117 * The interface allows clients to read information about the currently 118 * available overlays, change whether an overlay should be used or not, and 119 * change the relative order in which overlay packages are loaded. 120 * Read-access is granted if the request targets the same Android user as 121 * the caller runs as, or if the caller holds the 122 * INTERACT_ACROSS_USERS_FULL permission. Write-access is granted if the 123 * caller is granted read-access and additionaly holds the 124 * CHANGE_OVERLAY_PACKAGES permission.</li> 125 * </ul> 126 * 127 * <p>The AIDL interface works with String package names, int user IDs, and 128 * {@link OverlayInfo} objects. OverlayInfo instances are used to track a 129 * specific pair of target and overlay packages and include information such as 130 * the current state of the overlay. OverlayInfo objects are immutable.</p> 131 * 132 * <p>Internally, OverlayInfo objects are maintained by the 133 * OverlayManagerSettings class. The OMS and its helper classes are notified of 134 * changes to the settings by the OverlayManagerSettings.ChangeListener 135 * callback interface. The file /data/system/overlays.xml is used to persist 136 * the settings.</p> 137 * 138 * <p>Creation and deletion of idmap files are handled by the IdmapManager 139 * class.</p> 140 * 141 * <p>The following is an overview of OMS and its related classes. Note how box 142 * (2) does the heavy lifting, box (1) interacts with the Android framework, 143 * and box (3) replaces box (1) during unit testing.</p> 144 * 145 * <pre> 146 * Android framework 147 * | ^ 148 * . . . | . . . . | . . . . 149 * . | | . 150 * . AIDL, broadcasts . 151 * . intents | . 152 * . | | . . . . . . . . . . . . 153 * . v | . . 154 * . OverlayManagerService . OverlayManagerTests . 155 * . \ . / . 156 * . (1) \ . / (3) . 157 * . . . . . . . . . . \ . . . / . . . . . . . . . 158 * . \ / . 159 * . (2) \ / . 160 * . OverlayManagerServiceImpl . 161 * . | | . 162 * . | | . 163 * . OverlayManagerSettings IdmapManager . 164 * . . 165 * . . . . . . . . . . . . . . . . . . . . . . 166 * </pre> 167 * 168 * <p>Finally, here is a list of keywords used in the OMS context.</p> 169 * 170 * <ul> 171 * <li><b>target [package]</b> -- A regular apk that may have its resource 172 * pool extended by zero or more overlay packages.</li> 173 * 174 * <li><b>overlay [package]</b> -- An apk that provides additional 175 * resources to another apk.</li> 176 * 177 * <li><b>OMS</b> -- The OverlayManagerService, i.e. this class.</li> 178 * 179 * <li><b>approved</b> -- An overlay is approved if the OMS has verified 180 * that it can be used technically speaking (its target package is 181 * installed, at least one resource name in both packages match, the 182 * idmap was created, etc) and that it is secure to do so. External 183 * clients can not change this state.</li> 184 * 185 * <li><b>not approved</b> -- The opposite of approved.</li> 186 * 187 * <li><b>enabled</b> -- An overlay currently in active use and thus part 188 * of resource lookups. This requires the overlay to be approved. Only 189 * external clients can change this state.</li> 190 * 191 * <li><b>disabled</b> -- The opposite of enabled.</li> 192 * 193 * <li><b>idmap</b> -- A mapping of resource IDs between target and overlay 194 * used during resource lookup. Also the name of the binary that creates 195 * the mapping.</li> 196 * </ul> 197 */ 198 public final class OverlayManagerService extends SystemService { 199 static final String TAG = "OverlayManager"; 200 201 static final boolean DEBUG = false; 202 203 /** 204 * The system property that specifies the default overlays to apply. 205 * This is a semicolon separated list of package names. 206 * 207 * Ex: com.android.vendor.overlay_one;com.android.vendor.overlay_two 208 */ 209 private static final String DEFAULT_OVERLAYS_PROP = "ro.boot.vendor.overlay.theme"; 210 211 private final Object mLock = new Object(); 212 213 private final AtomicFile mSettingsFile; 214 215 private final PackageManagerHelper mPackageManager; 216 217 private final UserManagerService mUserManager; 218 219 private final OverlayManagerSettings mSettings; 220 221 private final OverlayManagerServiceImpl mImpl; 222 223 private final AtomicBoolean mPersistSettingsScheduled = new AtomicBoolean(false); 224 225 private Future<?> mInitCompleteSignal; 226 227 public OverlayManagerService(@NonNull final Context context, 228 @NonNull final Installer installer) { 229 super(context); 230 mSettingsFile = 231 new AtomicFile(new File(Environment.getDataSystemDirectory(), "overlays.xml")); 232 mPackageManager = new PackageManagerHelper(); 233 mUserManager = UserManagerService.getInstance(); 234 IdmapManager im = new IdmapManager(installer); 235 mSettings = new OverlayManagerSettings(); 236 mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings, 237 getDefaultOverlayPackages(), new OverlayChangeListener()); 238 mInitCompleteSignal = SystemServerInitThreadPool.get().submit(() -> { 239 final IntentFilter packageFilter = new IntentFilter(); 240 packageFilter.addAction(ACTION_PACKAGE_ADDED); 241 packageFilter.addAction(ACTION_PACKAGE_CHANGED); 242 packageFilter.addAction(ACTION_PACKAGE_REMOVED); 243 packageFilter.addDataScheme("package"); 244 getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL, 245 packageFilter, null, null); 246 247 final IntentFilter userFilter = new IntentFilter(); 248 userFilter.addAction(ACTION_USER_ADDED); 249 userFilter.addAction(ACTION_USER_REMOVED); 250 getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL, 251 userFilter, null, null); 252 253 restoreSettings(); 254 255 initIfNeeded(); 256 onSwitchUser(UserHandle.USER_SYSTEM); 257 258 publishBinderService(Context.OVERLAY_SERVICE, mService); 259 publishLocalService(OverlayManagerService.class, this); 260 }, "Init OverlayManagerService"); 261 } 262 263 @Override 264 public void onStart() { 265 // Intentionally left empty. 266 } 267 268 @Override 269 public void onBootPhase(int phase) { 270 if (phase == PHASE_SYSTEM_SERVICES_READY) { 271 ConcurrentUtils.waitForFutureNoInterrupt(mInitCompleteSignal, 272 "Wait for OverlayManagerService init"); 273 mInitCompleteSignal = null; 274 } 275 } 276 277 private void initIfNeeded() { 278 final UserManager um = getContext().getSystemService(UserManager.class); 279 final List<UserInfo> users = um.getUsers(true /*excludeDying*/); 280 synchronized (mLock) { 281 final int userCount = users.size(); 282 for (int i = 0; i < userCount; i++) { 283 final UserInfo userInfo = users.get(i); 284 if (!userInfo.supportsSwitchTo() && userInfo.id != UserHandle.USER_SYSTEM) { 285 // Initialize any users that can't be switched to, as there state would 286 // never be setup in onSwitchUser(). We will switch to the system user right 287 // after this, and its state will be setup there. 288 final List<String> targets = mImpl.updateOverlaysForUser(users.get(i).id); 289 updateOverlayPaths(users.get(i).id, targets); 290 } 291 } 292 } 293 } 294 295 @Override 296 public void onSwitchUser(final int newUserId) { 297 // ensure overlays in the settings are up-to-date, and propagate 298 // any asset changes to the rest of the system 299 synchronized (mLock) { 300 final List<String> targets = mImpl.updateOverlaysForUser(newUserId); 301 updateAssets(newUserId, targets); 302 } 303 schedulePersistSettings(); 304 } 305 306 private static Set<String> getDefaultOverlayPackages() { 307 final String str = SystemProperties.get(DEFAULT_OVERLAYS_PROP); 308 if (TextUtils.isEmpty(str)) { 309 return Collections.emptySet(); 310 } 311 312 final ArraySet<String> defaultPackages = new ArraySet<>(); 313 for (String packageName : str.split(";")) { 314 if (!TextUtils.isEmpty(packageName)) { 315 defaultPackages.add(packageName); 316 } 317 } 318 return defaultPackages; 319 } 320 321 private final class PackageReceiver extends BroadcastReceiver { 322 @Override 323 public void onReceive(@NonNull final Context context, @NonNull final Intent intent) { 324 final Uri data = intent.getData(); 325 if (data == null) { 326 Slog.e(TAG, "Cannot handle package broadcast with null data"); 327 return; 328 } 329 final String packageName = data.getSchemeSpecificPart(); 330 331 final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); 332 333 final int[] userIds; 334 final int extraUid = intent.getIntExtra(Intent.EXTRA_UID, UserHandle.USER_NULL); 335 if (extraUid == UserHandle.USER_NULL) { 336 userIds = mUserManager.getUserIds(); 337 } else { 338 userIds = new int[] { UserHandle.getUserId(extraUid) }; 339 } 340 341 switch (intent.getAction()) { 342 case ACTION_PACKAGE_ADDED: 343 if (replacing) { 344 onPackageUpgraded(packageName, userIds); 345 } else { 346 onPackageAdded(packageName, userIds); 347 } 348 break; 349 case ACTION_PACKAGE_CHANGED: 350 onPackageChanged(packageName, userIds); 351 break; 352 case ACTION_PACKAGE_REMOVED: 353 if (replacing) { 354 onPackageUpgrading(packageName, userIds); 355 } else { 356 onPackageRemoved(packageName, userIds); 357 } 358 break; 359 default: 360 // do nothing 361 break; 362 } 363 } 364 365 private void onPackageAdded(@NonNull final String packageName, 366 @NonNull final int[] userIds) { 367 for (final int userId : userIds) { 368 synchronized (mLock) { 369 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId, 370 false); 371 if (pi != null) { 372 mPackageManager.cachePackageInfo(packageName, userId, pi); 373 if (!isOverlayPackage(pi)) { 374 mImpl.onTargetPackageAdded(packageName, userId); 375 } else { 376 mImpl.onOverlayPackageAdded(packageName, userId); 377 } 378 } 379 } 380 } 381 } 382 383 private void onPackageChanged(@NonNull final String packageName, 384 @NonNull final int[] userIds) { 385 for (int userId : userIds) { 386 synchronized (mLock) { 387 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId, 388 false); 389 if (pi != null) { 390 mPackageManager.cachePackageInfo(packageName, userId, pi); 391 if (!isOverlayPackage(pi)) { 392 mImpl.onTargetPackageChanged(packageName, userId); 393 } else { 394 mImpl.onOverlayPackageChanged(packageName, userId); 395 } 396 } 397 } 398 } 399 } 400 401 private void onPackageUpgrading(@NonNull final String packageName, 402 @NonNull final int[] userIds) { 403 for (int userId : userIds) { 404 synchronized (mLock) { 405 mPackageManager.forgetPackageInfo(packageName, userId); 406 final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId); 407 if (oi == null) { 408 mImpl.onTargetPackageUpgrading(packageName, userId); 409 } else { 410 mImpl.onOverlayPackageUpgrading(packageName, userId); 411 } 412 } 413 } 414 } 415 416 private void onPackageUpgraded(@NonNull final String packageName, 417 @NonNull final int[] userIds) { 418 for (int userId : userIds) { 419 synchronized (mLock) { 420 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId, 421 false); 422 if (pi != null) { 423 mPackageManager.cachePackageInfo(packageName, userId, pi); 424 if (!isOverlayPackage(pi)) { 425 mImpl.onTargetPackageUpgraded(packageName, userId); 426 } else { 427 mImpl.onOverlayPackageUpgraded(packageName, userId); 428 } 429 } 430 } 431 } 432 } 433 434 private void onPackageRemoved(@NonNull final String packageName, 435 @NonNull final int[] userIds) { 436 for (int userId : userIds) { 437 synchronized (mLock) { 438 mPackageManager.forgetPackageInfo(packageName, userId); 439 final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId); 440 if (oi == null) { 441 mImpl.onTargetPackageRemoved(packageName, userId); 442 } else { 443 mImpl.onOverlayPackageRemoved(packageName, userId); 444 } 445 } 446 } 447 } 448 } 449 450 private final class UserReceiver extends BroadcastReceiver { 451 @Override 452 public void onReceive(@NonNull final Context context, @NonNull final Intent intent) { 453 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); 454 switch (intent.getAction()) { 455 case ACTION_USER_ADDED: 456 if (userId != UserHandle.USER_NULL) { 457 final ArrayList<String> targets; 458 synchronized (mLock) { 459 targets = mImpl.updateOverlaysForUser(userId); 460 } 461 updateOverlayPaths(userId, targets); 462 } 463 break; 464 465 case ACTION_USER_REMOVED: 466 if (userId != UserHandle.USER_NULL) { 467 synchronized (mLock) { 468 mImpl.onUserRemoved(userId); 469 mPackageManager.forgetAllPackageInfos(userId); 470 } 471 } 472 break; 473 default: 474 // do nothing 475 break; 476 } 477 } 478 } 479 480 private final IBinder mService = new IOverlayManager.Stub() { 481 @Override 482 public Map<String, List<OverlayInfo>> getAllOverlays(int userId) throws RemoteException { 483 userId = handleIncomingUser(userId, "getAllOverlays"); 484 485 synchronized (mLock) { 486 return mImpl.getOverlaysForUser(userId); 487 } 488 } 489 490 @Override 491 public List<OverlayInfo> getOverlayInfosForTarget(@Nullable final String targetPackageName, 492 int userId) throws RemoteException { 493 userId = handleIncomingUser(userId, "getOverlayInfosForTarget"); 494 if (targetPackageName == null) { 495 return Collections.emptyList(); 496 } 497 498 synchronized (mLock) { 499 return mImpl.getOverlayInfosForTarget(targetPackageName, userId); 500 } 501 } 502 503 @Override 504 public OverlayInfo getOverlayInfo(@Nullable final String packageName, 505 int userId) throws RemoteException { 506 userId = handleIncomingUser(userId, "getOverlayInfo"); 507 if (packageName == null) { 508 return null; 509 } 510 511 synchronized (mLock) { 512 return mImpl.getOverlayInfo(packageName, userId); 513 } 514 } 515 516 @Override 517 public boolean setEnabled(@Nullable final String packageName, final boolean enable, 518 int userId) throws RemoteException { 519 enforceChangeOverlayPackagesPermission("setEnabled"); 520 userId = handleIncomingUser(userId, "setEnabled"); 521 if (packageName == null) { 522 return false; 523 } 524 525 final long ident = Binder.clearCallingIdentity(); 526 try { 527 synchronized (mLock) { 528 return mImpl.setEnabled(packageName, enable, userId); 529 } 530 } finally { 531 Binder.restoreCallingIdentity(ident); 532 } 533 } 534 535 @Override 536 public boolean setEnabledExclusive(@Nullable final String packageName, final boolean enable, 537 int userId) throws RemoteException { 538 enforceChangeOverlayPackagesPermission("setEnabled"); 539 userId = handleIncomingUser(userId, "setEnabled"); 540 if (packageName == null || !enable) { 541 return false; 542 } 543 544 final long ident = Binder.clearCallingIdentity(); 545 try { 546 synchronized (mLock) { 547 return mImpl.setEnabledExclusive(packageName, userId); 548 } 549 } finally { 550 Binder.restoreCallingIdentity(ident); 551 } 552 } 553 554 @Override 555 public boolean setPriority(@Nullable final String packageName, 556 @Nullable final String parentPackageName, int userId) throws RemoteException { 557 enforceChangeOverlayPackagesPermission("setPriority"); 558 userId = handleIncomingUser(userId, "setPriority"); 559 if (packageName == null || parentPackageName == null) { 560 return false; 561 } 562 563 final long ident = Binder.clearCallingIdentity(); 564 try { 565 synchronized (mLock) { 566 return mImpl.setPriority(packageName, parentPackageName, userId); 567 } 568 } finally { 569 Binder.restoreCallingIdentity(ident); 570 } 571 } 572 573 @Override 574 public boolean setHighestPriority(@Nullable final String packageName, int userId) 575 throws RemoteException { 576 enforceChangeOverlayPackagesPermission("setHighestPriority"); 577 userId = handleIncomingUser(userId, "setHighestPriority"); 578 if (packageName == null) { 579 return false; 580 } 581 582 final long ident = Binder.clearCallingIdentity(); 583 try { 584 synchronized (mLock) { 585 return mImpl.setHighestPriority(packageName, userId); 586 } 587 } finally { 588 Binder.restoreCallingIdentity(ident); 589 } 590 } 591 592 @Override 593 public boolean setLowestPriority(@Nullable final String packageName, int userId) 594 throws RemoteException { 595 enforceChangeOverlayPackagesPermission("setLowestPriority"); 596 userId = handleIncomingUser(userId, "setLowestPriority"); 597 if (packageName == null) { 598 return false; 599 } 600 601 final long ident = Binder.clearCallingIdentity(); 602 try { 603 synchronized (mLock) { 604 return mImpl.setLowestPriority(packageName, userId); 605 } 606 } finally { 607 Binder.restoreCallingIdentity(ident); 608 } 609 } 610 611 @Override 612 public void onShellCommand(@NonNull final FileDescriptor in, 613 @NonNull final FileDescriptor out, @NonNull final FileDescriptor err, 614 @NonNull final String[] args, @NonNull final ShellCallback callback, 615 @NonNull final ResultReceiver resultReceiver) { 616 (new OverlayManagerShellCommand(this)).exec( 617 this, in, out, err, args, callback, resultReceiver); 618 } 619 620 @Override 621 protected void dump(@NonNull final FileDescriptor fd, @NonNull final PrintWriter pw, 622 @NonNull final String[] argv) { 623 enforceDumpPermission("dump"); 624 625 final boolean verbose = argv.length > 0 && "--verbose".equals(argv[0]); 626 627 synchronized (mLock) { 628 mImpl.onDump(pw); 629 mPackageManager.dump(pw, verbose); 630 } 631 } 632 633 /** 634 * Ensure that the caller has permission to interact with the given userId. 635 * If the calling user is not the same as the provided user, the caller needs 636 * to hold the INTERACT_ACROSS_USERS_FULL permission (or be system uid or 637 * root). 638 * 639 * @param userId the user to interact with 640 * @param message message for any SecurityException 641 */ 642 private int handleIncomingUser(final int userId, @NonNull final String message) { 643 return ActivityManager.handleIncomingUser(Binder.getCallingPid(), 644 Binder.getCallingUid(), userId, false, true, message, null); 645 } 646 647 /** 648 * Enforce that the caller holds the CHANGE_OVERLAY_PACKAGES permission (or is 649 * system or root). 650 * 651 * @param message used as message if SecurityException is thrown 652 * @throws SecurityException if the permission check fails 653 */ 654 private void enforceChangeOverlayPackagesPermission(@NonNull final String message) { 655 getContext().enforceCallingOrSelfPermission( 656 android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, message); 657 } 658 659 /** 660 * Enforce that the caller holds the DUMP permission (or is system or root). 661 * 662 * @param message used as message if SecurityException is thrown 663 * @throws SecurityException if the permission check fails 664 */ 665 private void enforceDumpPermission(@NonNull final String message) { 666 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, 667 message); 668 } 669 }; 670 671 private boolean isOverlayPackage(@NonNull final PackageInfo pi) { 672 return pi != null && pi.overlayTarget != null; 673 } 674 675 private final class OverlayChangeListener 676 implements OverlayManagerServiceImpl.OverlayChangeListener { 677 @Override 678 public void onOverlaysChanged(@NonNull final String targetPackageName, final int userId) { 679 schedulePersistSettings(); 680 FgThread.getHandler().post(() -> { 681 updateAssets(userId, targetPackageName); 682 683 final Intent intent = new Intent(Intent.ACTION_OVERLAY_CHANGED, 684 Uri.fromParts("package", targetPackageName, null)); 685 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 686 687 if (DEBUG) { 688 Slog.d(TAG, "send broadcast " + intent); 689 } 690 691 try { 692 ActivityManager.getService().broadcastIntent(null, intent, null, null, 0, 693 null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false, 694 userId); 695 } catch (RemoteException e) { 696 // Intentionally left empty. 697 } 698 }); 699 } 700 } 701 702 /** 703 * Updates the target packages' set of enabled overlays in PackageManager. 704 */ 705 private void updateOverlayPaths(int userId, List<String> targetPackageNames) { 706 if (DEBUG) { 707 Slog.d(TAG, "Updating overlay assets"); 708 } 709 final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class); 710 final boolean updateFrameworkRes = targetPackageNames.contains("android"); 711 if (updateFrameworkRes) { 712 targetPackageNames = pm.getTargetPackageNames(userId); 713 } 714 715 final Map<String, List<String>> pendingChanges = new ArrayMap<>(targetPackageNames.size()); 716 synchronized (mLock) { 717 final List<String> frameworkOverlays = 718 mImpl.getEnabledOverlayPackageNames("android", userId); 719 final int N = targetPackageNames.size(); 720 for (int i = 0; i < N; i++) { 721 final String targetPackageName = targetPackageNames.get(i); 722 List<String> list = new ArrayList<>(); 723 if (!"android".equals(targetPackageName)) { 724 list.addAll(frameworkOverlays); 725 } 726 list.addAll(mImpl.getEnabledOverlayPackageNames(targetPackageName, userId)); 727 pendingChanges.put(targetPackageName, list); 728 } 729 } 730 731 final int N = targetPackageNames.size(); 732 for (int i = 0; i < N; i++) { 733 final String targetPackageName = targetPackageNames.get(i); 734 if (DEBUG) { 735 Slog.d(TAG, "-> Updating overlay: target=" + targetPackageName + " overlays=[" 736 + TextUtils.join(",", pendingChanges.get(targetPackageName)) 737 + "] userId=" + userId); 738 } 739 740 if (!pm.setEnabledOverlayPackages( 741 userId, targetPackageName, pendingChanges.get(targetPackageName))) { 742 Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d", 743 targetPackageName, userId)); 744 } 745 } 746 } 747 748 private void updateAssets(final int userId, final String targetPackageName) { 749 updateAssets(userId, Collections.singletonList(targetPackageName)); 750 } 751 752 private void updateAssets(final int userId, List<String> targetPackageNames) { 753 updateOverlayPaths(userId, targetPackageNames); 754 final IActivityManager am = ActivityManager.getService(); 755 try { 756 am.scheduleApplicationInfoChanged(targetPackageNames, userId); 757 } catch (RemoteException e) { 758 // Intentionally left empty. 759 } 760 } 761 762 private void schedulePersistSettings() { 763 if (mPersistSettingsScheduled.getAndSet(true)) { 764 return; 765 } 766 IoThread.getHandler().post(() -> { 767 mPersistSettingsScheduled.set(false); 768 if (DEBUG) { 769 Slog.d(TAG, "Writing overlay settings"); 770 } 771 synchronized (mLock) { 772 FileOutputStream stream = null; 773 try { 774 stream = mSettingsFile.startWrite(); 775 mSettings.persist(stream); 776 mSettingsFile.finishWrite(stream); 777 } catch (IOException | XmlPullParserException e) { 778 mSettingsFile.failWrite(stream); 779 Slog.e(TAG, "failed to persist overlay state", e); 780 } 781 } 782 }); 783 } 784 785 private void restoreSettings() { 786 synchronized (mLock) { 787 if (!mSettingsFile.getBaseFile().exists()) { 788 return; 789 } 790 try (final FileInputStream stream = mSettingsFile.openRead()) { 791 mSettings.restore(stream); 792 793 // We might have data for dying users if the device was 794 // restarted before we received USER_REMOVED. Remove data for 795 // users that will not exist after the system is ready. 796 797 final List<UserInfo> liveUsers = mUserManager.getUsers(true /*excludeDying*/); 798 final int[] liveUserIds = new int[liveUsers.size()]; 799 for (int i = 0; i < liveUsers.size(); i++) { 800 liveUserIds[i] = liveUsers.get(i).getUserHandle().getIdentifier(); 801 } 802 Arrays.sort(liveUserIds); 803 804 for (int userId : mSettings.getUsers()) { 805 if (Arrays.binarySearch(liveUserIds, userId) < 0) { 806 mSettings.removeUser(userId); 807 } 808 } 809 } catch (IOException | XmlPullParserException e) { 810 Slog.e(TAG, "failed to restore overlay state", e); 811 } 812 } 813 } 814 815 private static final class PackageManagerHelper implements 816 OverlayManagerServiceImpl.PackageManagerHelper { 817 818 private final IPackageManager mPackageManager; 819 private final PackageManagerInternal mPackageManagerInternal; 820 821 // Use a cache for performance and for consistency within OMS: because 822 // additional PACKAGE_* intents may be delivered while we process an 823 // intent, querying the PackageManagerService for the actual current 824 // state may lead to contradictions within OMS. Better then to lag 825 // behind until all pending intents have been processed. 826 private final SparseArray<HashMap<String, PackageInfo>> mCache = new SparseArray<>(); 827 828 PackageManagerHelper() { 829 mPackageManager = getPackageManager(); 830 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); 831 } 832 833 public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId, 834 final boolean useCache) { 835 if (useCache) { 836 final PackageInfo cachedPi = getCachedPackageInfo(packageName, userId); 837 if (cachedPi != null) { 838 return cachedPi; 839 } 840 } 841 try { 842 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0, userId); 843 if (useCache && pi != null) { 844 cachePackageInfo(packageName, userId, pi); 845 } 846 return pi; 847 } catch (RemoteException e) { 848 // Intentionally left empty. 849 } 850 return null; 851 } 852 853 @Override 854 public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId) { 855 return getPackageInfo(packageName, userId, true); 856 } 857 858 @Override 859 public boolean signaturesMatching(@NonNull final String packageName1, 860 @NonNull final String packageName2, final int userId) { 861 // The package manager does not support different versions of packages 862 // to be installed for different users: ignore userId for now. 863 try { 864 return mPackageManager.checkSignatures( 865 packageName1, packageName2) == SIGNATURE_MATCH; 866 } catch (RemoteException e) { 867 // Intentionally left blank 868 } 869 return false; 870 } 871 872 @Override 873 public List<PackageInfo> getOverlayPackages(final int userId) { 874 return mPackageManagerInternal.getOverlayPackages(userId); 875 } 876 877 public PackageInfo getCachedPackageInfo(@NonNull final String packageName, 878 final int userId) { 879 final HashMap<String, PackageInfo> map = mCache.get(userId); 880 return map == null ? null : map.get(packageName); 881 } 882 883 public void cachePackageInfo(@NonNull final String packageName, final int userId, 884 @NonNull final PackageInfo pi) { 885 HashMap<String, PackageInfo> map = mCache.get(userId); 886 if (map == null) { 887 map = new HashMap<>(); 888 mCache.put(userId, map); 889 } 890 map.put(packageName, pi); 891 } 892 893 public void forgetPackageInfo(@NonNull final String packageName, final int userId) { 894 final HashMap<String, PackageInfo> map = mCache.get(userId); 895 if (map == null) { 896 return; 897 } 898 map.remove(packageName); 899 if (map.isEmpty()) { 900 mCache.delete(userId); 901 } 902 } 903 904 public void forgetAllPackageInfos(final int userId) { 905 mCache.delete(userId); 906 } 907 908 private static final String TAB1 = " "; 909 private static final String TAB2 = TAB1 + TAB1; 910 911 public void dump(@NonNull final PrintWriter pw, final boolean verbose) { 912 pw.println("PackageInfo cache"); 913 914 if (!verbose) { 915 int count = 0; 916 final int N = mCache.size(); 917 for (int i = 0; i < N; i++) { 918 final int userId = mCache.keyAt(i); 919 count += mCache.get(userId).size(); 920 } 921 pw.println(TAB1 + count + " package(s)"); 922 return; 923 } 924 925 if (mCache.size() == 0) { 926 pw.println(TAB1 + "<empty>"); 927 return; 928 } 929 930 final int N = mCache.size(); 931 for (int i = 0; i < N; i++) { 932 final int userId = mCache.keyAt(i); 933 pw.println(TAB1 + "User " + userId); 934 final HashMap<String, PackageInfo> map = mCache.get(userId); 935 for (Map.Entry<String, PackageInfo> entry : map.entrySet()) { 936 pw.println(TAB2 + entry.getKey() + ": " + entry.getValue()); 937 } 938 } 939 } 940 } 941 } 942