diff options
5 files changed, 167 insertions, 568 deletions
diff --git a/core/java/android/content/om/IOverlayManager.aidl b/core/java/android/content/om/IOverlayManager.aidl index 0b950b461285..44b5c4482599 100644 --- a/core/java/android/content/om/IOverlayManager.aidl +++ b/core/java/android/content/om/IOverlayManager.aidl @@ -17,7 +17,6 @@ package android.content.om; import android.content.om.OverlayInfo; -import android.content.om.OverlayManagerTransaction; /** * Api for getting information about overlay packages. @@ -164,18 +163,4 @@ interface IOverlayManager { * @param packageName The name of the overlay package whose idmap should be deleted. */ void invalidateCachesForOverlay(in String packageName, in int userIs); - - /** - * Perform a series of requests related to overlay packages. This is an - * atomic operation: either all requests were performed successfully and - * the changes were propagated to the rest of the system, or at least one - * request could not be performed successfully and nothing is changed and - * nothing is propagated to the rest of the system. - * - * @see OverlayManagerTransaction - * - * @param transaction the series of overlay related requests to perform - * @throws SecurityException if the transaction failed - */ - void commit(in OverlayManagerTransaction transaction); } diff --git a/core/java/android/content/om/OverlayManager.java b/core/java/android/content/om/OverlayManager.java index 7c14c2891d01..217f637cf9e3 100644 --- a/core/java/android/content/om/OverlayManager.java +++ b/core/java/android/content/om/OverlayManager.java @@ -254,29 +254,6 @@ public class OverlayManager { } /** - * Perform a series of requests related to overlay packages. This is an - * atomic operation: either all requests were performed successfully and - * the changes were propagated to the rest of the system, or at least one - * request could not be performed successfully and nothing is changed and - * nothing is propagated to the rest of the system. - * - * @see OverlayManagerTransaction - * - * @param transaction the series of overlay related requests to perform - * @throws Exception if not all the requests could be successfully and - * atomically executed - * - * @hide - */ - public void commit(@NonNull final OverlayManagerTransaction transaction) { - try { - mService.commit(transaction); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** * Starting on R, actor enforcement and app visibility changes introduce additional failure * cases, but the SecurityException thrown with these checks is unexpected for existing * consumers of the API. diff --git a/core/java/android/content/om/OverlayManagerTransaction.aidl b/core/java/android/content/om/OverlayManagerTransaction.aidl deleted file mode 100644 index 6715c82d4e6f..000000000000 --- a/core/java/android/content/om/OverlayManagerTransaction.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.om; - -parcelable OverlayManagerTransaction; diff --git a/core/java/android/content/om/OverlayManagerTransaction.java b/core/java/android/content/om/OverlayManagerTransaction.java deleted file mode 100644 index 1fa8973c35b5..000000000000 --- a/core/java/android/content/om/OverlayManagerTransaction.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.om; - -import static com.android.internal.util.Preconditions.checkNotNull; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.UserHandle; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * Container for a batch of requests to the OverlayManagerService. - * - * Transactions are created using a builder interface. Example usage: - * - * final OverlayManager om = ctx.getSystemService(OverlayManager.class); - * final OverlayManagerTransaction t = new OverlayManagerTransaction.Builder() - * .setEnabled(...) - * .setEnabled(...) - * .build(); - * om.commit(t); - * - * @hide - */ -public class OverlayManagerTransaction - implements Iterable<OverlayManagerTransaction.Request>, Parcelable { - // TODO: remove @hide from this class when OverlayManager is added to the - // SDK, but keep OverlayManagerTransaction.Request @hidden - private final List<Request> mRequests; - - OverlayManagerTransaction(@NonNull final List<Request> requests) { - checkNotNull(requests); - if (requests.contains(null)) { - throw new IllegalArgumentException("null request"); - } - mRequests = requests; - } - - private OverlayManagerTransaction(@NonNull final Parcel source) { - final int size = source.readInt(); - mRequests = new ArrayList<Request>(size); - for (int i = 0; i < size; i++) { - final int request = source.readInt(); - final String packageName = source.readString(); - final int userId = source.readInt(); - mRequests.add(new Request(request, packageName, userId)); - } - } - - @Override - public Iterator<Request> iterator() { - return mRequests.iterator(); - } - - @Override - public String toString() { - return String.format("OverlayManagerTransaction { mRequests = %s }", mRequests); - } - - /** - * A single unit of the transaction, such as a request to enable an - * overlay, or to disable an overlay. - * - * @hide - */ - public static class Request { - @IntDef(prefix = "TYPE_", value = { - TYPE_SET_ENABLED, - TYPE_SET_DISABLED, - }) - @Retention(RetentionPolicy.SOURCE) - @interface RequestType {} - - public static final int TYPE_SET_ENABLED = 0; - public static final int TYPE_SET_DISABLED = 1; - - @RequestType public final int type; - public final String packageName; - public final int userId; - - public Request(@RequestType final int type, @NonNull final String packageName, - final int userId) { - this.type = type; - this.packageName = packageName; - this.userId = userId; - } - - @Override - public String toString() { - return String.format("Request{type=0x%02x (%s), packageName=%s, userId=%d}", - type, typeToString(), packageName, userId); - } - - /** - * Translate the request type into a human readable string. Only - * intended for debugging. - * - * @hide - */ - public String typeToString() { - switch (type) { - case TYPE_SET_ENABLED: return "TYPE_SET_ENABLED"; - case TYPE_SET_DISABLED: return "TYPE_SET_DISABLED"; - default: return String.format("TYPE_UNKNOWN (0x%02x)", type); - } - } - } - - /** - * Builder class for OverlayManagerTransaction objects. - * - * @hide - */ - public static class Builder { - private final List<Request> mRequests = new ArrayList<>(); - - /** - * Request that an overlay package be enabled and change its loading - * order to the last package to be loaded, or disabled - * - * If the caller has the correct permissions, it is always possible to - * disable an overlay. Due to technical and security reasons it may not - * always be possible to enable an overlay, for instance if the overlay - * does not successfully overlay any target resources due to - * overlayable policy restrictions. - * - * An enabled overlay is a part of target package's resources, i.e. it will - * be part of any lookups performed via {@link android.content.res.Resources} - * and {@link android.content.res.AssetManager}. A disabled overlay will no - * longer affect the resources of the target package. If the target is - * currently running, its outdated resources will be replaced by new ones. - * - * @param packageName The name of the overlay package. - * @param enable true to enable the overlay, false to disable it. - * @return this Builder object, so you can chain additional requests - */ - public Builder setEnabled(@NonNull String packageName, boolean enable) { - return setEnabled(packageName, enable, UserHandle.myUserId()); - } - - /** - * @hide - */ - public Builder setEnabled(@NonNull String packageName, boolean enable, int userId) { - checkNotNull(packageName); - @Request.RequestType final int type = - enable ? Request.TYPE_SET_ENABLED : Request.TYPE_SET_DISABLED; - mRequests.add(new Request(type, packageName, userId)); - return this; - } - - /** - * Create a new transaction out of the requests added so far. Execute - * the transaction by calling OverlayManager#commit. - * - * @see OverlayManager#commit - * @return a new transaction - */ - public OverlayManagerTransaction build() { - return new OverlayManagerTransaction(mRequests); - } - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - final int size = mRequests.size(); - dest.writeInt(size); - for (int i = 0; i < size; i++) { - final Request req = mRequests.get(i); - dest.writeInt(req.type); - dest.writeString(req.packageName); - dest.writeInt(req.userId); - } - } - - public static final Parcelable.Creator<OverlayManagerTransaction> CREATOR = - new Parcelable.Creator<OverlayManagerTransaction>() { - - @Override - public OverlayManagerTransaction createFromParcel(Parcel source) { - return new OverlayManagerTransaction(source); - } - - @Override - public OverlayManagerTransaction[] newArray(int size) { - return new OverlayManagerTransaction[size]; - } - }; -} diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index 7a6792c121c0..437e33d66c91 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -24,8 +24,6 @@ import static android.content.Intent.ACTION_PACKAGE_REMOVED; import static android.content.Intent.ACTION_USER_ADDED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_REASON; -import static android.content.om.OverlayManagerTransaction.Request.TYPE_SET_DISABLED; -import static android.content.om.OverlayManagerTransaction.Request.TYPE_SET_ENABLED; import static android.content.pm.PackageManager.SIGNATURE_MATCH; import static android.os.Trace.TRACE_TAG_RRO; import static android.os.Trace.traceBegin; @@ -43,7 +41,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.om.IOverlayManager; import android.content.om.OverlayInfo; -import android.content.om.OverlayManagerTransaction; import android.content.om.OverlayableInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; @@ -87,14 +84,11 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Optional; -import java.util.Set; import java.util.function.Consumer; /** @@ -244,13 +238,8 @@ public final class OverlayManagerService extends SystemService { private final OverlayActorEnforcer mActorEnforcer; - private final Consumer<PackageAndUser> mPropagateOverlayChange = (pair) -> { - persistSettings(); - FgThread.getHandler().post(() -> { - List<String> affectedTargets = updatePackageManager(pair.packageName, pair.userId); - updateActivityManager(affectedTargets, pair.userId); - broadcastActionOverlayChanged(affectedTargets, pair.userId); - }); + private final Consumer<PackageAndUser> mOnOverlaysChanged = (pair) -> { + onOverlaysChanged(pair.packageName, pair.userId); }; public OverlayManagerService(@NonNull final Context context) { @@ -309,11 +298,11 @@ public final class OverlayManagerService extends SystemService { for (int i = 0; i < userCount; i++) { final UserInfo userInfo = users.get(i); if (!userInfo.supportsSwitchTo() && userInfo.id != UserHandle.USER_SYSTEM) { - // Initialize any users that can't be switched to, as their state would + // Initialize any users that can't be switched to, as there state would // never be setup in onSwitchUser(). We will switch to the system user right // after this, and its state will be setup there. final List<String> targets = mImpl.updateOverlaysForUser(users.get(i).id); - updatePackageManager(targets, users.get(i).id); + updateOverlayPaths(users.get(i).id, targets); } } } @@ -327,8 +316,7 @@ public final class OverlayManagerService extends SystemService { // any asset changes to the rest of the system synchronized (mLock) { final List<String> targets = mImpl.updateOverlaysForUser(newUserId); - final List<String> affectedTargets = updatePackageManager(targets, newUserId); - updateActivityManager(affectedTargets, newUserId); + updateAssets(newUserId, targets); } persistSettings(); } finally { @@ -418,10 +406,10 @@ public final class OverlayManagerService extends SystemService { try { if (pi.isOverlayPackage()) { mImpl.onOverlayPackageAdded(packageName, userId) - .ifPresent(mPropagateOverlayChange); + .ifPresent(mOnOverlaysChanged); } else { mImpl.onTargetPackageAdded(packageName, userId) - .ifPresent(mPropagateOverlayChange); + .ifPresent(mOnOverlaysChanged); } } catch (OperationFailedException e) { Slog.e(TAG, "onPackageAdded internal error", e); @@ -448,10 +436,10 @@ public final class OverlayManagerService extends SystemService { try { if (pi.isOverlayPackage()) { mImpl.onOverlayPackageChanged(packageName, userId) - .ifPresent(mPropagateOverlayChange); + .ifPresent(mOnOverlaysChanged); } else { mImpl.onTargetPackageChanged(packageName, userId) - .ifPresent(mPropagateOverlayChange); + .ifPresent(mOnOverlaysChanged); } } catch (OperationFailedException e) { Slog.e(TAG, "onPackageChanged internal error", e); @@ -475,7 +463,7 @@ public final class OverlayManagerService extends SystemService { if (oi != null) { try { mImpl.onOverlayPackageReplacing(packageName, userId) - .ifPresent(mPropagateOverlayChange); + .ifPresent(mOnOverlaysChanged); } catch (OperationFailedException e) { Slog.e(TAG, "onPackageReplacing internal error", e); } @@ -500,10 +488,10 @@ public final class OverlayManagerService extends SystemService { try { if (pi.isOverlayPackage()) { mImpl.onOverlayPackageReplaced(packageName, userId) - .ifPresent(mPropagateOverlayChange); + .ifPresent(mOnOverlaysChanged); } else { mImpl.onTargetPackageReplaced(packageName, userId) - .ifPresent(mPropagateOverlayChange); + .ifPresent(mOnOverlaysChanged); } } catch (OperationFailedException e) { Slog.e(TAG, "onPackageReplaced internal error", e); @@ -528,10 +516,10 @@ public final class OverlayManagerService extends SystemService { try { if (oi != null) { mImpl.onOverlayPackageRemoved(packageName, userId) - .ifPresent(mPropagateOverlayChange); + .ifPresent(mOnOverlaysChanged); } else { mImpl.onTargetPackageRemoved(packageName, userId) - .ifPresent(mPropagateOverlayChange); + .ifPresent(mOnOverlaysChanged); } } catch (OperationFailedException e) { Slog.e(TAG, "onPackageRemoved internal error", e); @@ -557,7 +545,7 @@ public final class OverlayManagerService extends SystemService { synchronized (mLock) { targets = mImpl.updateOverlaysForUser(userId); } - updatePackageManager(targets, userId); + updateOverlayPaths(userId, targets); } finally { traceEnd(TRACE_TAG_RRO); } @@ -654,7 +642,7 @@ public final class OverlayManagerService extends SystemService { synchronized (mLock) { try { mImpl.setEnabled(packageName, enable, realUserId) - .ifPresent(mPropagateOverlayChange); + .ifPresent(mOnOverlaysChanged); return true; } catch (OperationFailedException e) { return false; @@ -686,7 +674,7 @@ public final class OverlayManagerService extends SystemService { try { mImpl.setEnabledExclusive(packageName, false /* withinCategory */, realUserId) - .ifPresent(mPropagateOverlayChange); + .ifPresent(mOnOverlaysChanged); return true; } catch (OperationFailedException e) { return false; @@ -719,7 +707,7 @@ public final class OverlayManagerService extends SystemService { try { mImpl.setEnabledExclusive(packageName, true /* withinCategory */, realUserId) - .ifPresent(mPropagateOverlayChange); + .ifPresent(mOnOverlaysChanged); return true; } catch (OperationFailedException e) { return false; @@ -751,7 +739,7 @@ public final class OverlayManagerService extends SystemService { synchronized (mLock) { try { mImpl.setPriority(packageName, parentPackageName, realUserId) - .ifPresent(mPropagateOverlayChange); + .ifPresent(mOnOverlaysChanged); return true; } catch (OperationFailedException e) { return false; @@ -781,7 +769,7 @@ public final class OverlayManagerService extends SystemService { synchronized (mLock) { try { mImpl.setHighestPriority(packageName, realUserId) - .ifPresent(mPropagateOverlayChange); + .ifPresent(mOnOverlaysChanged); return true; } catch (OperationFailedException e) { return false; @@ -811,7 +799,7 @@ public final class OverlayManagerService extends SystemService { synchronized (mLock) { try { mImpl.setLowestPriority(packageName, realUserId) - .ifPresent(mPropagateOverlayChange); + .ifPresent(mOnOverlaysChanged); return true; } catch (OperationFailedException e) { return false; @@ -864,120 +852,6 @@ public final class OverlayManagerService extends SystemService { } @Override - public void commit(@NonNull final OverlayManagerTransaction transaction) - throws RemoteException { - try { - traceBegin(TRACE_TAG_RRO, "OMS#commit " + transaction); - try { - executeAllRequests(transaction); - } catch (Exception e) { - final long ident = Binder.clearCallingIdentity(); - try { - restoreSettings(); - } finally { - Binder.restoreCallingIdentity(ident); - } - Slog.d(TAG, "commit failed: " + e.getMessage(), e); - throw new SecurityException("commit failed" - + (DEBUG ? ": " + e.getMessage() : "")); - } - } finally { - traceEnd(TRACE_TAG_RRO); - } - } - - private Optional<PackageAndUser> executeRequest( - @NonNull final OverlayManagerTransaction.Request request) throws Exception { - final int realUserId = handleIncomingUser(request.userId, request.typeToString()); - enforceActor(request.packageName, request.typeToString(), realUserId); - - final long ident = Binder.clearCallingIdentity(); - try { - switch (request.type) { - case TYPE_SET_ENABLED: - Optional<PackageAndUser> opt1 = - mImpl.setEnabled(request.packageName, true, request.userId); - Optional<PackageAndUser> opt2 = - mImpl.setHighestPriority(request.packageName, request.userId); - // Both setEnabled and setHighestPriority affected the same - // target package and user: if both return non-empty - // Optionals, they are identical - return opt1.isPresent() ? opt1 : opt2; - case TYPE_SET_DISABLED: - return mImpl.setEnabled(request.packageName, false, request.userId); - default: - throw new IllegalArgumentException("unsupported request: " + request); - } - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - private void executeAllRequests(@NonNull final OverlayManagerTransaction transaction) - throws Exception { - if (DEBUG) { - Slog.d(TAG, "commit " + transaction); - } - if (transaction == null) { - throw new IllegalArgumentException("null transaction"); - } - - // map: userId -> list<targetPackageName> - SparseArray<List<String>> affectedTargetsToUpdate = new SparseArray<>(); - - synchronized (mLock) { - // map: userId -> set<targetPackageName> - SparseArray<Set<String>> targetsToUpdate = new SparseArray<>(); - - // execute the requests (as calling user) - for (final OverlayManagerTransaction.Request request : transaction) { - executeRequest(request).ifPresent(target -> { - Set<String> userTargets = targetsToUpdate.get(target.userId); - if (userTargets == null) { - userTargets = new ArraySet<String>(); - targetsToUpdate.put(target.userId, userTargets); - } - userTargets.add(target.packageName); - }); - } - - // past the point of no return: the entire transaction has been - // processed successfully, we can no longer fail: continue as - // system_server - final long ident = Binder.clearCallingIdentity(); - try { - persistSettings(); - - // inform the package manager about the new paths - for (int index = 0; index < targetsToUpdate.size(); index++) { - final int userId = targetsToUpdate.keyAt(index); - final List<String> affectedTargets = - updatePackageManager(targetsToUpdate.valueAt(index), userId); - affectedTargetsToUpdate.put(userId, affectedTargets); - } - } finally { - Binder.restoreCallingIdentity(ident); - } - } // synchronized (mLock) - - FgThread.getHandler().post(() -> { - final long ident = Binder.clearCallingIdentity(); - try { - // schedule apps to refresh + broadcast the ACTION_OVERLAY_CHANGED intents - for (int index = 0; index < affectedTargetsToUpdate.size(); index++) { - final int userId = affectedTargetsToUpdate.keyAt(index); - final List<String> packageNames = affectedTargetsToUpdate.valueAt(index); - - updateActivityManager(packageNames, userId); - broadcastActionOverlayChanged(packageNames, userId); - } - } finally { - Binder.restoreCallingIdentity(ident); - } - }); - } - - @Override public void onShellCommand(@NonNull final FileDescriptor in, @NonNull final FileDescriptor out, @NonNull final FileDescriptor err, @NonNull final String[] args, @NonNull final ShellCallback callback, @@ -1098,7 +972,152 @@ public final class OverlayManagerService extends SystemService { } }; - private static final class PackageManagerHelperImpl implements PackageManagerHelper { + private void onOverlaysChanged(@NonNull final String targetPackageName, final int userId) { + persistSettings(); + FgThread.getHandler().post(() -> { + updateAssets(userId, targetPackageName); + + final Intent intent = new Intent(ACTION_OVERLAY_CHANGED, + Uri.fromParts("package", targetPackageName, null)); + intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + + if (DEBUG) { + Slog.d(TAG, "send broadcast " + intent); + } + + try { + ActivityManager.getService().broadcastIntent(null, intent, null, null, 0, + null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false, + userId); + } catch (RemoteException e) { + // Intentionally left empty. + } + }); + } + + /** + * Updates the target packages' set of enabled overlays in PackageManager. + */ + private ArrayList<String> updateOverlayPaths(int userId, List<String> targetPackageNames) { + try { + traceBegin(TRACE_TAG_RRO, "OMS#updateOverlayPaths " + targetPackageNames); + if (DEBUG) { + Slog.d(TAG, "Updating overlay assets"); + } + final PackageManagerInternal pm = + LocalServices.getService(PackageManagerInternal.class); + final boolean updateFrameworkRes = targetPackageNames.contains("android"); + if (updateFrameworkRes) { + targetPackageNames = pm.getTargetPackageNames(userId); + } + + final Map<String, List<String>> pendingChanges = + new ArrayMap<>(targetPackageNames.size()); + synchronized (mLock) { + final List<String> frameworkOverlays = + mImpl.getEnabledOverlayPackageNames("android", userId); + final int n = targetPackageNames.size(); + for (int i = 0; i < n; i++) { + final String targetPackageName = targetPackageNames.get(i); + List<String> list = new ArrayList<>(); + if (!"android".equals(targetPackageName)) { + list.addAll(frameworkOverlays); + } + list.addAll(mImpl.getEnabledOverlayPackageNames(targetPackageName, userId)); + pendingChanges.put(targetPackageName, list); + } + } + + final HashSet<String> updatedPackages = new HashSet<>(); + final int n = targetPackageNames.size(); + for (int i = 0; i < n; i++) { + final String targetPackageName = targetPackageNames.get(i); + if (DEBUG) { + Slog.d(TAG, "-> Updating overlay: target=" + targetPackageName + " overlays=[" + + TextUtils.join(",", pendingChanges.get(targetPackageName)) + + "] userId=" + userId); + } + + if (!pm.setEnabledOverlayPackages( + userId, targetPackageName, pendingChanges.get(targetPackageName), + updatedPackages)) { + Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d", + targetPackageName, userId)); + } + } + return new ArrayList<>(updatedPackages); + } finally { + traceEnd(TRACE_TAG_RRO); + } + } + + private void updateAssets(final int userId, final String targetPackageName) { + updateAssets(userId, Collections.singletonList(targetPackageName)); + } + + private void updateAssets(final int userId, List<String> targetPackageNames) { + final IActivityManager am = ActivityManager.getService(); + try { + final ArrayList<String> updatedPaths = updateOverlayPaths(userId, targetPackageNames); + am.scheduleApplicationInfoChanged(updatedPaths, userId); + } catch (RemoteException e) { + // Intentionally left empty. + } + } + + private void persistSettings() { + if (DEBUG) { + Slog.d(TAG, "Writing overlay settings"); + } + synchronized (mLock) { + FileOutputStream stream = null; + try { + stream = mSettingsFile.startWrite(); + mSettings.persist(stream); + mSettingsFile.finishWrite(stream); + } catch (IOException | XmlPullParserException e) { + mSettingsFile.failWrite(stream); + Slog.e(TAG, "failed to persist overlay state", e); + } + } + } + + private void restoreSettings() { + try { + traceBegin(TRACE_TAG_RRO, "OMS#restoreSettings"); + synchronized (mLock) { + if (!mSettingsFile.getBaseFile().exists()) { + return; + } + try (FileInputStream stream = mSettingsFile.openRead()) { + mSettings.restore(stream); + + // We might have data for dying users if the device was + // restarted before we received USER_REMOVED. Remove data for + // users that will not exist after the system is ready. + + final List<UserInfo> liveUsers = mUserManager.getUsers(true /*excludeDying*/); + final int[] liveUserIds = new int[liveUsers.size()]; + for (int i = 0; i < liveUsers.size(); i++) { + liveUserIds[i] = liveUsers.get(i).getUserHandle().getIdentifier(); + } + Arrays.sort(liveUserIds); + + for (int userId : mSettings.getUsers()) { + if (Arrays.binarySearch(liveUserIds, userId) < 0) { + mSettings.removeUser(userId); + } + } + } catch (IOException | XmlPullParserException e) { + Slog.e(TAG, "failed to restore overlay state", e); + } + } + } finally { + traceEnd(TRACE_TAG_RRO); + } + } + + private static final class PackageManagerHelperImpl implements PackageManagerHelper { private final Context mContext; private final IPackageManager mPackageManager; @@ -1308,151 +1327,4 @@ public final class OverlayManagerService extends SystemService { } } } - - // Helper methods to update other parts of the system or read/write - // settings: these methods should never call into each other! - - private void broadcastActionOverlayChanged(@NonNull final Collection<String> packageNames, - final int userId) { - for (final String packageName : packageNames) { - broadcastActionOverlayChanged(packageName, userId); - } - } - - private void broadcastActionOverlayChanged(@NonNull final String targetPackageName, - final int userId) { - final Intent intent = new Intent(ACTION_OVERLAY_CHANGED, - Uri.fromParts("package", targetPackageName, null)); - intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - try { - ActivityManager.getService().broadcastIntent(null, intent, null, null, 0, null, null, - null, android.app.AppOpsManager.OP_NONE, null, false, false, userId); - } catch (RemoteException e) { - // Intentionally left empty. - } - } - - /** - * Tell the activity manager to tell a set of packages to reload their - * resources. - */ - private void updateActivityManager(List<String> targetPackageNames, final int userId) { - final IActivityManager am = ActivityManager.getService(); - try { - am.scheduleApplicationInfoChanged(targetPackageNames, userId); - } catch (RemoteException e) { - // Intentionally left empty. - } - } - - private ArrayList<String> updatePackageManager(String targetPackageNames, final int userId) { - return updatePackageManager(Collections.singletonList(targetPackageNames), userId); - } - - /** - * Updates the target packages' set of enabled overlays in PackageManager. - * @return the package names of affected targets (a superset of - * targetPackageNames: the target themserlves and shared libraries) - */ - private ArrayList<String> updatePackageManager(@NonNull Collection<String> targetPackageNames, - final int userId) { - try { - traceBegin(TRACE_TAG_RRO, "OMS#updatePackageManager " + targetPackageNames); - if (DEBUG) { - Slog.d(TAG, "Update package manager about changed overlays"); - } - final PackageManagerInternal pm = - LocalServices.getService(PackageManagerInternal.class); - final boolean updateFrameworkRes = targetPackageNames.contains("android"); - if (updateFrameworkRes) { - targetPackageNames = pm.getTargetPackageNames(userId); - } - - final Map<String, List<String>> pendingChanges = - new ArrayMap<>(targetPackageNames.size()); - synchronized (mLock) { - final List<String> frameworkOverlays = - mImpl.getEnabledOverlayPackageNames("android", userId); - for (final String targetPackageName : targetPackageNames) { - List<String> list = new ArrayList<>(); - if (!"android".equals(targetPackageName)) { - list.addAll(frameworkOverlays); - } - list.addAll(mImpl.getEnabledOverlayPackageNames(targetPackageName, userId)); - pendingChanges.put(targetPackageName, list); - } - } - - final HashSet<String> updatedPackages = new HashSet<>(); - for (final String targetPackageName : targetPackageNames) { - if (DEBUG) { - Slog.d(TAG, "-> Updating overlay: target=" + targetPackageName + " overlays=[" - + TextUtils.join(",", pendingChanges.get(targetPackageName)) - + "] userId=" + userId); - } - - if (!pm.setEnabledOverlayPackages( - userId, targetPackageName, pendingChanges.get(targetPackageName), - updatedPackages)) { - Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d", - targetPackageName, userId)); - } - } - return new ArrayList<>(updatedPackages); - } finally { - traceEnd(TRACE_TAG_RRO); - } - } - - private void persistSettings() { - if (DEBUG) { - Slog.d(TAG, "Writing overlay settings"); - } - synchronized (mLock) { - FileOutputStream stream = null; - try { - stream = mSettingsFile.startWrite(); - mSettings.persist(stream); - mSettingsFile.finishWrite(stream); - } catch (IOException | XmlPullParserException e) { - mSettingsFile.failWrite(stream); - Slog.e(TAG, "failed to persist overlay state", e); - } - } - } - - private void restoreSettings() { - try { - traceBegin(TRACE_TAG_RRO, "OMS#restoreSettings"); - synchronized (mLock) { - if (!mSettingsFile.getBaseFile().exists()) { - return; - } - try (FileInputStream stream = mSettingsFile.openRead()) { - mSettings.restore(stream); - - // We might have data for dying users if the device was - // restarted before we received USER_REMOVED. Remove data for - // users that will not exist after the system is ready. - - final List<UserInfo> liveUsers = mUserManager.getUsers(true /*excludeDying*/); - final int[] liveUserIds = new int[liveUsers.size()]; - for (int i = 0; i < liveUsers.size(); i++) { - liveUserIds[i] = liveUsers.get(i).getUserHandle().getIdentifier(); - } - Arrays.sort(liveUserIds); - - for (int userId : mSettings.getUsers()) { - if (Arrays.binarySearch(liveUserIds, userId) < 0) { - mSettings.removeUser(userId); - } - } - } catch (IOException | XmlPullParserException e) { - Slog.e(TAG, "failed to restore overlay state", e); - } - } - } finally { - traceEnd(TRACE_TAG_RRO); - } - } } |