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