Merge "Revert "OMS: add transactional API"" am: 7facc4ec41 am: ba88e64636
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1548437 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: I6d5bf83f5d5ce2600084e4c2be28199ffe78db22
This commit is contained in:
@@ -17,7 +17,6 @@
|
|||||||
package android.content.om;
|
package android.content.om;
|
||||||
|
|
||||||
import android.content.om.OverlayInfo;
|
import android.content.om.OverlayInfo;
|
||||||
import android.content.om.OverlayManagerTransaction;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Api for getting information about overlay packages.
|
* 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.
|
* @param packageName The name of the overlay package whose idmap should be deleted.
|
||||||
*/
|
*/
|
||||||
void invalidateCachesForOverlay(in String packageName, in int userIs);
|
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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,29 +253,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
|
* Starting on R, actor enforcement and app visibility changes introduce additional failure
|
||||||
* cases, but the SecurityException thrown with these checks is unexpected for existing
|
* cases, but the SecurityException thrown with these checks is unexpected for existing
|
||||||
|
|||||||
@@ -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;
|
|
||||||
@@ -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];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -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_ADDED;
|
||||||
import static android.content.Intent.ACTION_USER_REMOVED;
|
import static android.content.Intent.ACTION_USER_REMOVED;
|
||||||
import static android.content.Intent.EXTRA_REASON;
|
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.content.pm.PackageManager.SIGNATURE_MATCH;
|
||||||
import static android.os.Trace.TRACE_TAG_RRO;
|
import static android.os.Trace.TRACE_TAG_RRO;
|
||||||
import static android.os.Trace.traceBegin;
|
import static android.os.Trace.traceBegin;
|
||||||
@@ -43,7 +41,6 @@ import android.content.Intent;
|
|||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.om.IOverlayManager;
|
import android.content.om.IOverlayManager;
|
||||||
import android.content.om.OverlayInfo;
|
import android.content.om.OverlayInfo;
|
||||||
import android.content.om.OverlayManagerTransaction;
|
|
||||||
import android.content.om.OverlayableInfo;
|
import android.content.om.OverlayableInfo;
|
||||||
import android.content.pm.IPackageManager;
|
import android.content.pm.IPackageManager;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
@@ -87,14 +84,11 @@ import java.io.IOException;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -244,13 +238,8 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
|
|
||||||
private final OverlayActorEnforcer mActorEnforcer;
|
private final OverlayActorEnforcer mActorEnforcer;
|
||||||
|
|
||||||
private final Consumer<PackageAndUser> mPropagateOverlayChange = (pair) -> {
|
private final Consumer<PackageAndUser> mOnOverlaysChanged = (pair) -> {
|
||||||
persistSettings();
|
onOverlaysChanged(pair.packageName, pair.userId);
|
||||||
FgThread.getHandler().post(() -> {
|
|
||||||
List<String> affectedTargets = updatePackageManager(pair.packageName, pair.userId);
|
|
||||||
updateActivityManager(affectedTargets, pair.userId);
|
|
||||||
broadcastActionOverlayChanged(affectedTargets, pair.userId);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public OverlayManagerService(@NonNull final Context context) {
|
public OverlayManagerService(@NonNull final Context context) {
|
||||||
@@ -309,11 +298,11 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
for (int i = 0; i < userCount; i++) {
|
for (int i = 0; i < userCount; i++) {
|
||||||
final UserInfo userInfo = users.get(i);
|
final UserInfo userInfo = users.get(i);
|
||||||
if (!userInfo.supportsSwitchTo() && userInfo.id != UserHandle.USER_SYSTEM) {
|
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
|
// never be setup in onSwitchUser(). We will switch to the system user right
|
||||||
// after this, and its state will be setup there.
|
// after this, and its state will be setup there.
|
||||||
final List<String> targets = mImpl.updateOverlaysForUser(users.get(i).id);
|
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
|
// any asset changes to the rest of the system
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
final List<String> targets = mImpl.updateOverlaysForUser(newUserId);
|
final List<String> targets = mImpl.updateOverlaysForUser(newUserId);
|
||||||
final List<String> affectedTargets = updatePackageManager(targets, newUserId);
|
updateAssets(newUserId, targets);
|
||||||
updateActivityManager(affectedTargets, newUserId);
|
|
||||||
}
|
}
|
||||||
persistSettings();
|
persistSettings();
|
||||||
} finally {
|
} finally {
|
||||||
@@ -418,10 +406,10 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
try {
|
try {
|
||||||
if (pi.isOverlayPackage()) {
|
if (pi.isOverlayPackage()) {
|
||||||
mImpl.onOverlayPackageAdded(packageName, userId)
|
mImpl.onOverlayPackageAdded(packageName, userId)
|
||||||
.ifPresent(mPropagateOverlayChange);
|
.ifPresent(mOnOverlaysChanged);
|
||||||
} else {
|
} else {
|
||||||
mImpl.onTargetPackageAdded(packageName, userId)
|
mImpl.onTargetPackageAdded(packageName, userId)
|
||||||
.ifPresent(mPropagateOverlayChange);
|
.ifPresent(mOnOverlaysChanged);
|
||||||
}
|
}
|
||||||
} catch (OperationFailedException e) {
|
} catch (OperationFailedException e) {
|
||||||
Slog.e(TAG, "onPackageAdded internal error", e);
|
Slog.e(TAG, "onPackageAdded internal error", e);
|
||||||
@@ -448,10 +436,10 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
try {
|
try {
|
||||||
if (pi.isOverlayPackage()) {
|
if (pi.isOverlayPackage()) {
|
||||||
mImpl.onOverlayPackageChanged(packageName, userId)
|
mImpl.onOverlayPackageChanged(packageName, userId)
|
||||||
.ifPresent(mPropagateOverlayChange);
|
.ifPresent(mOnOverlaysChanged);
|
||||||
} else {
|
} else {
|
||||||
mImpl.onTargetPackageChanged(packageName, userId)
|
mImpl.onTargetPackageChanged(packageName, userId)
|
||||||
.ifPresent(mPropagateOverlayChange);
|
.ifPresent(mOnOverlaysChanged);
|
||||||
}
|
}
|
||||||
} catch (OperationFailedException e) {
|
} catch (OperationFailedException e) {
|
||||||
Slog.e(TAG, "onPackageChanged internal error", e);
|
Slog.e(TAG, "onPackageChanged internal error", e);
|
||||||
@@ -475,7 +463,7 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
if (oi != null) {
|
if (oi != null) {
|
||||||
try {
|
try {
|
||||||
mImpl.onOverlayPackageReplacing(packageName, userId)
|
mImpl.onOverlayPackageReplacing(packageName, userId)
|
||||||
.ifPresent(mPropagateOverlayChange);
|
.ifPresent(mOnOverlaysChanged);
|
||||||
} catch (OperationFailedException e) {
|
} catch (OperationFailedException e) {
|
||||||
Slog.e(TAG, "onPackageReplacing internal error", e);
|
Slog.e(TAG, "onPackageReplacing internal error", e);
|
||||||
}
|
}
|
||||||
@@ -500,10 +488,10 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
try {
|
try {
|
||||||
if (pi.isOverlayPackage()) {
|
if (pi.isOverlayPackage()) {
|
||||||
mImpl.onOverlayPackageReplaced(packageName, userId)
|
mImpl.onOverlayPackageReplaced(packageName, userId)
|
||||||
.ifPresent(mPropagateOverlayChange);
|
.ifPresent(mOnOverlaysChanged);
|
||||||
} else {
|
} else {
|
||||||
mImpl.onTargetPackageReplaced(packageName, userId)
|
mImpl.onTargetPackageReplaced(packageName, userId)
|
||||||
.ifPresent(mPropagateOverlayChange);
|
.ifPresent(mOnOverlaysChanged);
|
||||||
}
|
}
|
||||||
} catch (OperationFailedException e) {
|
} catch (OperationFailedException e) {
|
||||||
Slog.e(TAG, "onPackageReplaced internal error", e);
|
Slog.e(TAG, "onPackageReplaced internal error", e);
|
||||||
@@ -528,10 +516,10 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
try {
|
try {
|
||||||
if (oi != null) {
|
if (oi != null) {
|
||||||
mImpl.onOverlayPackageRemoved(packageName, userId)
|
mImpl.onOverlayPackageRemoved(packageName, userId)
|
||||||
.ifPresent(mPropagateOverlayChange);
|
.ifPresent(mOnOverlaysChanged);
|
||||||
} else {
|
} else {
|
||||||
mImpl.onTargetPackageRemoved(packageName, userId)
|
mImpl.onTargetPackageRemoved(packageName, userId)
|
||||||
.ifPresent(mPropagateOverlayChange);
|
.ifPresent(mOnOverlaysChanged);
|
||||||
}
|
}
|
||||||
} catch (OperationFailedException e) {
|
} catch (OperationFailedException e) {
|
||||||
Slog.e(TAG, "onPackageRemoved internal error", e);
|
Slog.e(TAG, "onPackageRemoved internal error", e);
|
||||||
@@ -557,7 +545,7 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
targets = mImpl.updateOverlaysForUser(userId);
|
targets = mImpl.updateOverlaysForUser(userId);
|
||||||
}
|
}
|
||||||
updatePackageManager(targets, userId);
|
updateOverlayPaths(userId, targets);
|
||||||
} finally {
|
} finally {
|
||||||
traceEnd(TRACE_TAG_RRO);
|
traceEnd(TRACE_TAG_RRO);
|
||||||
}
|
}
|
||||||
@@ -654,7 +642,7 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
try {
|
try {
|
||||||
mImpl.setEnabled(packageName, enable, realUserId)
|
mImpl.setEnabled(packageName, enable, realUserId)
|
||||||
.ifPresent(mPropagateOverlayChange);
|
.ifPresent(mOnOverlaysChanged);
|
||||||
return true;
|
return true;
|
||||||
} catch (OperationFailedException e) {
|
} catch (OperationFailedException e) {
|
||||||
return false;
|
return false;
|
||||||
@@ -686,7 +674,7 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
try {
|
try {
|
||||||
mImpl.setEnabledExclusive(packageName,
|
mImpl.setEnabledExclusive(packageName,
|
||||||
false /* withinCategory */, realUserId)
|
false /* withinCategory */, realUserId)
|
||||||
.ifPresent(mPropagateOverlayChange);
|
.ifPresent(mOnOverlaysChanged);
|
||||||
return true;
|
return true;
|
||||||
} catch (OperationFailedException e) {
|
} catch (OperationFailedException e) {
|
||||||
return false;
|
return false;
|
||||||
@@ -719,7 +707,7 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
try {
|
try {
|
||||||
mImpl.setEnabledExclusive(packageName,
|
mImpl.setEnabledExclusive(packageName,
|
||||||
true /* withinCategory */, realUserId)
|
true /* withinCategory */, realUserId)
|
||||||
.ifPresent(mPropagateOverlayChange);
|
.ifPresent(mOnOverlaysChanged);
|
||||||
return true;
|
return true;
|
||||||
} catch (OperationFailedException e) {
|
} catch (OperationFailedException e) {
|
||||||
return false;
|
return false;
|
||||||
@@ -751,7 +739,7 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
try {
|
try {
|
||||||
mImpl.setPriority(packageName, parentPackageName, realUserId)
|
mImpl.setPriority(packageName, parentPackageName, realUserId)
|
||||||
.ifPresent(mPropagateOverlayChange);
|
.ifPresent(mOnOverlaysChanged);
|
||||||
return true;
|
return true;
|
||||||
} catch (OperationFailedException e) {
|
} catch (OperationFailedException e) {
|
||||||
return false;
|
return false;
|
||||||
@@ -781,7 +769,7 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
try {
|
try {
|
||||||
mImpl.setHighestPriority(packageName, realUserId)
|
mImpl.setHighestPriority(packageName, realUserId)
|
||||||
.ifPresent(mPropagateOverlayChange);
|
.ifPresent(mOnOverlaysChanged);
|
||||||
return true;
|
return true;
|
||||||
} catch (OperationFailedException e) {
|
} catch (OperationFailedException e) {
|
||||||
return false;
|
return false;
|
||||||
@@ -811,7 +799,7 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
try {
|
try {
|
||||||
mImpl.setLowestPriority(packageName, realUserId)
|
mImpl.setLowestPriority(packageName, realUserId)
|
||||||
.ifPresent(mPropagateOverlayChange);
|
.ifPresent(mOnOverlaysChanged);
|
||||||
return true;
|
return true;
|
||||||
} catch (OperationFailedException e) {
|
} catch (OperationFailedException e) {
|
||||||
return false;
|
return false;
|
||||||
@@ -863,120 +851,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
|
@Override
|
||||||
public void onShellCommand(@NonNull final FileDescriptor in,
|
public void onShellCommand(@NonNull final FileDescriptor in,
|
||||||
@NonNull final FileDescriptor out, @NonNull final FileDescriptor err,
|
@NonNull final FileDescriptor out, @NonNull final FileDescriptor err,
|
||||||
@@ -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 Context mContext;
|
||||||
private final IPackageManager mPackageManager;
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user