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