Add overlay management functions into OverlayManager
Self-Targeting apps can manage the overlays by the following classes.
* OverlayManager
* OverlayManagerTransaction
For OverlayManager, it provides 2 functions for the app.
* Start a overlay manager transaction
OverlayManager#beginTransaction()
* List the registered overlays
OverlayManager#getOverlayInfosForTarget(targetPackage).
For OverlayManagerTransaction, it provides 3 functions for the app.
* register a FabricatedOverlay
OverlayManagerTransaction#registerFabricatedOverlay
* unregister a FabricatedOverlay
OverlayManagerTransaction#unregisterFabricatedOverlay
* commit the transaction
OverlayManagerTransaction#commit
Test: atest \
OverlayHostTests \
OverlayDeviceTests \
SelfTargetingOverlayDeviceTests \
OverlayRemountedTest \
FrameworksServicesTests:com.android.server.om \
CtsContentTestCases:android.content.om.cts \
idmap2_tests
Bug: 205919743
Change-Id: I3b0b60a30689b3d033f96cfcf02e2f67b480f207
diff --git a/core/java/android/content/om/OverlayManager.java b/core/java/android/content/om/OverlayManager.java
index 812f6b0..ed1f6a2 100644
--- a/core/java/android/content/om/OverlayManager.java
+++ b/core/java/android/content/om/OverlayManager.java
@@ -17,6 +17,7 @@
package android.content.om;
import android.annotation.NonNull;
+import android.annotation.NonUiContext;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
@@ -25,12 +26,16 @@
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import com.android.internal.content.om.OverlayManagerImpl;
+
+import java.io.IOException;
import java.util.List;
/**
@@ -76,6 +81,7 @@
private final IOverlayManager mService;
private final Context mContext;
+ private final OverlayManagerImpl mOverlayManagerImpl;
/**
* Pre R a {@link java.lang.SecurityException} would only be thrown by setEnabled APIs (e
@@ -117,6 +123,7 @@
public OverlayManager(Context context, IOverlayManager service) {
mContext = context;
mService = service;
+ mOverlayManagerImpl = new OverlayManagerImpl(context);
}
/** @hide */
@@ -301,6 +308,17 @@
* @hide
*/
public void commit(@NonNull final OverlayManagerTransaction transaction) {
+ if (transaction.isSelfTargetingTransaction()
+ || mService == null
+ || mService.asBinder() == null) {
+ try {
+ commitSelfTarget(transaction);
+ } catch (PackageManager.NameNotFoundException | IOException e) {
+ throw new RuntimeException(e);
+ }
+ return;
+ }
+
try {
mService.commit(transaction);
} catch (RemoteException e) {
@@ -332,4 +350,48 @@
throw e;
}
}
+
+ /**
+ * Get a OverlayManagerTransaction.Builder to build out a overlay manager transaction.
+ *
+ * @return a builder of the overlay manager transaction.
+ * @hide
+ */
+ @NonNull
+ public OverlayManagerTransaction.Builder beginTransaction() {
+ return new OverlayManagerTransaction.Builder(this);
+ }
+
+ /**
+ * Commit the self-targeting transaction to register or unregister overlays.
+ *
+ * <p>Applications can request OverlayManager to register overlays and unregister the registered
+ * overlays via {@link OverlayManagerTransaction}.
+ *
+ * @throws IOException if there is a file operation error.
+ * @throws PackageManager.NameNotFoundException if the package name is not found.
+ * @hide
+ */
+ @NonUiContext
+ void commitSelfTarget(@NonNull final OverlayManagerTransaction transaction)
+ throws PackageManager.NameNotFoundException, IOException {
+ synchronized (mOverlayManagerImpl) {
+ mOverlayManagerImpl.commit(transaction);
+ }
+ }
+
+ /**
+ * Get the related information of overlays for {@code targetPackageName}.
+ *
+ * @param targetPackageName the target package name
+ * @return a list of overlay information
+ * @hide
+ */
+ @NonNull
+ @NonUiContext
+ public List<OverlayInfo> getOverlayInfosForTarget(@NonNull final String targetPackageName) {
+ synchronized (mOverlayManagerImpl) {
+ return mOverlayManagerImpl.getOverlayInfosForTarget(targetPackageName);
+ }
+ }
}
diff --git a/core/java/android/content/om/OverlayManagerTransaction.java b/core/java/android/content/om/OverlayManagerTransaction.java
index 868dab2..42b3ef3 100644
--- a/core/java/android/content/om/OverlayManagerTransaction.java
+++ b/core/java/android/content/om/OverlayManagerTransaction.java
@@ -20,19 +20,22 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.NonUiContext;
import android.annotation.Nullable;
-import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
+import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
/**
* Container for a batch of requests to the OverlayManagerService.
@@ -53,13 +56,16 @@
// TODO: remove @hide from this class when OverlayManager is added to the
// SDK, but keep OverlayManagerTransaction.Request @hidden
private final List<Request> mRequests;
+ private final OverlayManager mOverlayManager;
- OverlayManagerTransaction(@NonNull final List<Request> requests) {
+ OverlayManagerTransaction(
+ @NonNull final List<Request> requests, @Nullable OverlayManager overlayManager) {
checkNotNull(requests);
if (requests.contains(null)) {
throw new IllegalArgumentException("null request");
}
mRequests = requests;
+ mOverlayManager = overlayManager;
}
private OverlayManagerTransaction(@NonNull final Parcel source) {
@@ -72,6 +78,7 @@
final Bundle extras = source.readBundle(null);
mRequests.add(new Request(request, overlay, userId, extras));
}
+ mOverlayManager = null;
}
@Override
@@ -156,6 +163,20 @@
*/
public static class Builder {
private final List<Request> mRequests = new ArrayList<>();
+ @Nullable private final OverlayManager mOverlayManager;
+
+ public Builder() {
+ mOverlayManager = null;
+ }
+
+ /**
+ * The transaction builder for self-targeting.
+ *
+ * @param overlayManager is not null if the transaction is for self-targeting.
+ */
+ Builder(@NonNull OverlayManager overlayManager) {
+ mOverlayManager = Objects.requireNonNull(overlayManager);
+ }
/**
* Request that an overlay package be enabled and change its loading
@@ -205,7 +226,10 @@
*
* @hide
*/
+ @NonNull
public Builder registerFabricatedOverlay(@NonNull FabricatedOverlay overlay) {
+ Objects.requireNonNull(overlay);
+
final Bundle extras = new Bundle();
extras.putParcelable(Request.BUNDLE_FABRICATED_OVERLAY, overlay.mOverlay);
mRequests.add(new Request(Request.TYPE_REGISTER_FABRICATED, overlay.getIdentifier(),
@@ -220,7 +244,10 @@
*
* @hide
*/
+ @NonNull
public Builder unregisterFabricatedOverlay(@NonNull OverlayIdentifier overlay) {
+ Objects.requireNonNull(overlay);
+
mRequests.add(new Request(Request.TYPE_UNREGISTER_FABRICATED, overlay,
UserHandle.USER_ALL));
return this;
@@ -233,8 +260,9 @@
* @see OverlayManager#commit
* @return a new transaction
*/
+ @NonNull
public OverlayManagerTransaction build() {
- return new OverlayManagerTransaction(mRequests);
+ return new OverlayManagerTransaction(mRequests, mOverlayManager);
}
}
@@ -269,4 +297,23 @@
return new OverlayManagerTransaction[size];
}
};
+
+ /**
+ * Commit the overlay manager transaction to register or unregister overlays for self-targeting.
+ *
+ * <p>Applications can register overlays and unregister the registered overlays via {@link
+ * OverlayManagerTransaction}.
+ *
+ * @throws IOException if there is a file operation error.
+ * @throws PackageManager.NameNotFoundException if the package name is not found.
+ * @hide
+ */
+ @NonUiContext
+ public void commit() throws PackageManager.NameNotFoundException, IOException {
+ mOverlayManager.commitSelfTarget(this);
+ }
+
+ boolean isSelfTargetingTransaction() {
+ return mOverlayManager != null;
+ }
}