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