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