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