summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/om/IOverlayManager.aidl15
-rw-r--r--core/java/android/content/om/OverlayManager.java23
-rw-r--r--core/java/android/content/om/OverlayManagerTransaction.aidl19
-rw-r--r--core/java/android/content/om/OverlayManagerTransaction.java216
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerService.java462
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);
- }
- }
}