diff --git a/core/java/android/content/om/OverlayManager.java b/core/java/android/content/om/OverlayManager.java index 812f6b0fc34be..ed1f6a2b1457f 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.Compatibility; 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 @@ public class OverlayManager { 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 class OverlayManager { public OverlayManager(Context context, IOverlayManager service) { mContext = context; mService = service; + mOverlayManagerImpl = new OverlayManagerImpl(context); } /** @hide */ @@ -301,6 +308,17 @@ public class OverlayManager { * @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 @@ public class OverlayManager { 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. + * + *

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 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 868dab2981086..42b3ef3c370d0 100644 --- a/core/java/android/content/om/OverlayManagerTransaction.java +++ b/core/java/android/content/om/OverlayManagerTransaction.java @@ -20,19 +20,22 @@ import static com.android.internal.util.Preconditions.checkNotNull; 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 @@ public class OverlayManagerTransaction // TODO: remove @hide from this class when OverlayManager is added to the // SDK, but keep OverlayManagerTransaction.Request @hidden private final List mRequests; + private final OverlayManager mOverlayManager; - OverlayManagerTransaction(@NonNull final List requests) { + OverlayManagerTransaction( + @NonNull final List 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 @@ public class OverlayManagerTransaction final Bundle extras = source.readBundle(null); mRequests.add(new Request(request, overlay, userId, extras)); } + mOverlayManager = null; } @Override @@ -156,6 +163,20 @@ public class OverlayManagerTransaction */ public static class Builder { private final List 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 @@ public class OverlayManagerTransaction * * @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 @@ public class OverlayManagerTransaction * * @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 @@ public class OverlayManagerTransaction * @see OverlayManager#commit * @return a new transaction */ + @NonNull public OverlayManagerTransaction build() { - return new OverlayManagerTransaction(mRequests); + return new OverlayManagerTransaction(mRequests, mOverlayManager); } } @@ -269,4 +297,23 @@ public class OverlayManagerTransaction return new OverlayManagerTransaction[size]; } }; + + /** + * Commit the overlay manager transaction to register or unregister overlays for self-targeting. + * + *

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; + } }