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