• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.content.om;
18 
19 import android.annotation.NonNull;
20 import android.annotation.NonUiContext;
21 import android.annotation.Nullable;
22 import android.annotation.RequiresPermission;
23 import android.annotation.SuppressLint;
24 import android.annotation.SystemApi;
25 import android.annotation.SystemService;
26 import android.compat.Compatibility;
27 import android.compat.annotation.ChangeId;
28 import android.compat.annotation.EnabledSince;
29 import android.content.Context;
30 import android.content.pm.PackageManager;
31 import android.os.Build;
32 import android.os.RemoteException;
33 import android.os.ServiceManager;
34 import android.os.UserHandle;
35 
36 import com.android.internal.content.om.OverlayManagerImpl;
37 
38 import java.io.IOException;
39 import java.util.List;
40 
41 /**
42  * OverlayManager gives apps the ability to create an {@link OverlayManagerTransaction} to
43  * maintain the overlays and list the registered fabricated runtime resources overlays(FRROs).
44  *
45  * <p>OverlayManager returns the list of overlays to the app calling {@link
46  * #getOverlayInfosForTarget(String)}. The app starts an {@link OverlayManagerTransaction} to manage
47  * the overlays. The app can achieve the following by using {@link OverlayManagerTransaction}.
48  *
49  * <ul>
50  *   <li>register overlays
51  *   <li>unregister overlays
52  *   <li>execute multiple operations in one commitment by calling {@link
53  *       #commit(OverlayManagerTransaction)}
54  * </ul>
55  *
56  * @see OverlayManagerTransaction
57  */
58 @SystemService(Context.OVERLAY_SERVICE)
59 public class OverlayManager {
60 
61     private final IOverlayManager mService;
62     private final OverlayManagerImpl mOverlayManagerImpl;
63 
64     /**
65      * Pre R a {@link java.lang.SecurityException} would only be thrown by setEnabled APIs (e
66      * .g. {@code #setEnabled(String, boolean, UserHandle)}) for a permission error.
67      * Since R this no longer holds true, and {@link java.lang.SecurityException} can be
68      * thrown for any number of reasons, none of which are exposed to the caller.
69      *
70      * <p>To maintain existing API behavior, if a legacy permission failure or actor enforcement
71      * failure occurs for an app not yet targeting R, coerce it into an {@link
72      * java.lang.IllegalStateException}, which existed in the source prior to R.
73      */
74     @ChangeId
75     @EnabledSince(targetSdkVersion = Build.VERSION_CODES.R)
76     private static final long THROW_SECURITY_EXCEPTIONS = 147340954;
77 
78     /**
79      * Applications can use OverlayManager to create overlays to overlay on itself resources. The
80      * overlay target is itself, or the Android package, and the work range is only in caller
81      * application.
82      *
83      * <p>In {@link android.content.Context#getSystemService(String)}, it crashes because of {@link
84      * java.lang.NullPointerException} if the parameter is OverlayManager. if the self-targeting is
85      * enabled, the caller application can get the OverlayManager instance to use self-targeting
86      * functionality.
87      *
88      * @hide
89      */
90     @ChangeId
91     @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
92     public static final long SELF_TARGETING_OVERLAY = 205919743;
93 
94     /**
95      * Creates a new instance.
96      *
97      * Updates OverlayManager state; gets information about installed overlay packages.
98      * <p>Users of this API must be actors of any overlays they desire to change the state of.
99      *
100      * <p>An actor is a package responsible for managing the state of overlays targeting
101      * overlayables that specify the actor. For example, an actor may enable or disable an overlay
102      * or otherwise change its state.
103      *
104      * <p>Actors are specified as part of the overlayable definition.
105      *
106      * <pre>{@code
107      * <overlayable name="OverlayableResourcesName" actor="overlay://namespace/actorName">
108      * }</pre></p>
109      *
110      * <p>Actors are defined through {@code com.android.server.SystemConfig}. Only system packages
111      * can be used. The namespace "android" is reserved for use by AOSP and any "android"
112      * definitions must have an implementation on device that fulfill their intended functionality.
113      *
114      * <pre>{@code
115      * <named-actor
116      *     namespace="namespace"
117      *     name="actorName"
118      *     package="com.example.pkg"
119      *     />
120      * }</pre></p>
121      *
122      * <p>An actor can manipulate a particular overlay if any of the following is true:
123      * <ul>
124      * <li>its UID is {@link android.os.Process#ROOT_UID}, {@link android.os.Process#SYSTEM_UID}
125      * </li>
126      * <li>it is the target of the overlay package</li>
127      * <li>it has the CHANGE_OVERLAY_PACKAGES permission and the target does not specify an actor
128      * </li>
129      * <li>it is the actor specified by the overlayable</li>
130      * </ul></p>
131      *
132      * @param context The current context in which to operate.
133      * @param service The backing system service.
134      *
135      * @hide
136      */
137     @SuppressLint("ReferencesHidden")
OverlayManager(@onNull Context context, @Nullable IOverlayManager service)138     public OverlayManager(@NonNull Context context, @Nullable IOverlayManager service) {
139         mService = service;
140         mOverlayManagerImpl = new OverlayManagerImpl(context);
141     }
142 
143     /** @hide */
144     @SuppressLint("ReferencesHidden")
OverlayManager(@onNull Context context)145     public OverlayManager(@NonNull Context context) {
146         this(context, IOverlayManager.Stub.asInterface(
147             ServiceManager.getService(Context.OVERLAY_SERVICE)));
148     }
149 
150     /**
151      * Request that an overlay package is enabled and any other overlay packages with the same
152      * target package and category are disabled.
153      *
154      * If a set of overlay packages share the same category, single call to this method is
155      * equivalent to multiple calls to {@code #setEnabled(String, boolean, UserHandle)}.
156      *
157      * The caller must pass the actor requirements specified in the class comment.
158      *
159      * @param packageName the name of the overlay package to enable.
160      * @param user The user for which to change the overlay.
161      *
162      * @throws SecurityException when caller is not allowed to enable {@code packageName}
163      * @throws IllegalStateException when enabling fails otherwise
164      *
165      * @hide
166      */
167     @SystemApi
168     @RequiresPermission(anyOf = {
169             "android.permission.INTERACT_ACROSS_USERS",
170             "android.permission.INTERACT_ACROSS_USERS_FULL"
171     })
setEnabledExclusiveInCategory(@onNull final String packageName, @NonNull UserHandle user)172     public void setEnabledExclusiveInCategory(@NonNull final String packageName,
173             @NonNull UserHandle user) throws SecurityException, IllegalStateException {
174         try {
175             if (!mService.setEnabledExclusiveInCategory(packageName, user.getIdentifier())) {
176                 throw new IllegalStateException("setEnabledExclusiveInCategory failed");
177             }
178         } catch (SecurityException e) {
179             rethrowSecurityException(e);
180         } catch (RemoteException e) {
181             throw e.rethrowFromSystemServer();
182         }
183     }
184 
185     /**
186      * Request that an overlay package is enabled or disabled.
187      *
188      * While {@link #setEnabledExclusiveInCategory(String, UserHandle)} doesn't support disabling
189      * every overlay in a category, this method allows you to disable everything.
190      *
191      * The caller must pass the actor requirements specified in the class comment.
192      *
193      * @param packageName the name of the overlay package to enable.
194      * @param enable {@code false} if the overlay should be turned off.
195      * @param user The user for which to change the overlay.
196      *
197      * @throws SecurityException when caller is not allowed to enable/disable {@code packageName}
198      * @throws IllegalStateException when enabling/disabling fails otherwise
199      *
200      * @hide
201      */
202     @SystemApi
203     @RequiresPermission(anyOf = {
204             "android.permission.INTERACT_ACROSS_USERS",
205             "android.permission.INTERACT_ACROSS_USERS_FULL"
206     })
setEnabled(@onNull final String packageName, final boolean enable, @NonNull UserHandle user)207     public void setEnabled(@NonNull final String packageName, final boolean enable,
208             @NonNull UserHandle user) throws SecurityException, IllegalStateException {
209         try {
210             if (!mService.setEnabled(packageName, enable, user.getIdentifier())) {
211                 throw new IllegalStateException("setEnabled failed");
212             }
213         } catch (SecurityException e) {
214             rethrowSecurityException(e);
215         } catch (RemoteException e) {
216             throw e.rethrowFromSystemServer();
217         }
218     }
219 
220     /**
221      * Enable an overlay package for a specific set of constraints. In case of multiple constraints,
222      * the overlay would be enabled when any of the given constraints are satisfied.
223      *
224      * Re-enabling an overlay with new constraints updates the constraints for the overlay.
225      *
226      * The caller must pass the actor requirements specified in the class comment.
227      *
228      * @param packageName the name of the overlay package to enable.
229      * @param user The user for which to change the overlay.
230      * @param constraints list of {@link OverlayConstraint} for enabling the overlay.
231      *
232      * @throws SecurityException when caller is not allowed to enable {@code packageName}
233      * @throws IllegalStateException when enabling fails otherwise
234      *
235      * @see OverlayConstraint
236      *
237      * @hide
238      */
239     @RequiresPermission(anyOf = {
240             "android.permission.INTERACT_ACROSS_USERS",
241             "android.permission.INTERACT_ACROSS_USERS_FULL"
242     })
enableWithConstraints(@onNull final String packageName, @NonNull UserHandle user, @Nullable final List<OverlayConstraint> constraints)243     public void enableWithConstraints(@NonNull final String packageName, @NonNull UserHandle user,
244             @Nullable final List<OverlayConstraint> constraints)
245             throws SecurityException, IllegalStateException {
246         try {
247             if (!mService.enableWithConstraints(packageName, user.getIdentifier(), constraints)) {
248                 throw new IllegalStateException("enableWithConstraints failed");
249             }
250         } catch (SecurityException e) {
251             rethrowSecurityException(e);
252         } catch (RemoteException e) {
253             throw e.rethrowFromSystemServer();
254         }
255     }
256 
257     /**
258      * Returns information about the overlay with the given package name for
259      * the specified user.
260      *
261      * @param packageName The name of the package.
262      * @param userHandle The user to get the OverlayInfos for.
263      * @return An OverlayInfo object; if no overlays exist with the
264      *         requested package name, null is returned.
265      *
266      * @hide
267      */
268     @SystemApi
269     @Nullable
getOverlayInfo(@onNull final String packageName, @NonNull final UserHandle userHandle)270     public OverlayInfo getOverlayInfo(@NonNull final String packageName,
271             @NonNull final UserHandle userHandle) {
272         try {
273             return mService.getOverlayInfo(packageName, userHandle.getIdentifier());
274         } catch (RemoteException e) {
275             throw e.rethrowFromSystemServer();
276         }
277     }
278 
279     /**
280      * Returns information about the overlay represented by the identifier for the specified user.
281      *
282      * @param overlay the identifier representing the overlay
283      * @param userHandle the user of which to get overlay state info
284      * @return the overlay info or null if the overlay cannot be found
285      *
286      * @hide
287      */
288     @Nullable
getOverlayInfo(@onNull final OverlayIdentifier overlay, @NonNull final UserHandle userHandle)289     public OverlayInfo getOverlayInfo(@NonNull final OverlayIdentifier overlay,
290             @NonNull final UserHandle userHandle) {
291         try {
292             return mService.getOverlayInfoByIdentifier(overlay, userHandle.getIdentifier());
293         } catch (RemoteException e) {
294             throw e.rethrowFromSystemServer();
295         }
296     }
297 
298     /**
299      * Returns information about all overlays for the given target package for
300      * the specified user. The returned list is ordered according to the
301      * overlay priority with the highest priority at the end of the list.
302      *
303      * @param targetPackageName The name of the target package.
304      * @param user The user to get the OverlayInfos for.
305      * @return A list of OverlayInfo objects; if no overlays exist for the
306      *         requested package, an empty list is returned.
307      *
308      * @hide
309      */
310     @SystemApi
311     @RequiresPermission(anyOf = {
312             "android.permission.INTERACT_ACROSS_USERS",
313             "android.permission.INTERACT_ACROSS_USERS_FULL"
314     })
315     @NonNull
getOverlayInfosForTarget(@onNull final String targetPackageName, @NonNull UserHandle user)316     public List<OverlayInfo> getOverlayInfosForTarget(@NonNull final String targetPackageName,
317             @NonNull UserHandle user) {
318         try {
319             return mService.getOverlayInfosForTarget(targetPackageName, user.getIdentifier());
320         } catch (RemoteException e) {
321             throw e.rethrowFromSystemServer();
322         }
323     }
324 
325     /**
326      * Clear part of the overlay manager's internal cache of PackageInfo
327      * objects. Only intended for testing.
328      *
329      * @param targetPackageName The name of the target package.
330      * @param user The user to get the OverlayInfos for.
331      *
332      * @hide
333      */
334     @RequiresPermission(anyOf = {
335             "android.permission.INTERACT_ACROSS_USERS",
336     })
invalidateCachesForOverlay(@onNull final String targetPackageName, @NonNull UserHandle user)337     public void invalidateCachesForOverlay(@NonNull final String targetPackageName,
338             @NonNull UserHandle user) {
339         try {
340             mService.invalidateCachesForOverlay(targetPackageName, user.getIdentifier());
341         } catch (RemoteException e) {
342             throw e.rethrowFromSystemServer();
343         }
344     }
345 
346     /**
347      * Perform a series of requests related to overlay packages. This is an
348      * atomic operation: either all requests were performed successfully and
349      * the changes were propagated to the rest of the system, or at least one
350      * request could not be performed successfully and nothing is changed and
351      * nothing is propagated to the rest of the system.
352      *
353      * @see OverlayManagerTransaction
354      *
355      * @param transaction the series of overlay related requests to perform
356      * @throws Exception if not all the requests could be successfully and
357      *         atomically executed
358      *
359      * @hide
360      */
commitToSystemServer(@onNull final OverlayManagerTransaction transaction)361     private void commitToSystemServer(@NonNull final OverlayManagerTransaction transaction) {
362         try {
363             mService.commit(transaction);
364         } catch (RemoteException e) {
365             throw e.rethrowFromSystemServer();
366         }
367     }
368 
369     /**
370      * Commit the overlay manager transaction.
371      *
372      * <p>Applications can register overlays and unregister the registered overlays in an atomic
373      * operation via {@link OverlayManagerTransaction}.
374      *
375      * @see OverlayManagerTransaction
376      *
377      * @param transaction the series of overlay related requests to perform
378      * @throws Exception if not all the requests could be successfully
379      */
commit(@onNull final OverlayManagerTransaction transaction)380     public void commit(@NonNull final OverlayManagerTransaction transaction) {
381         if (transaction.isSelfTargeting()
382                 || mService == null
383                 || mService.asBinder() == null) {
384             try {
385                 commitSelfTarget(transaction);
386             } catch (PackageManager.NameNotFoundException | IOException e) {
387                 throw new RuntimeException(e);
388             }
389             return;
390         }
391 
392         commitToSystemServer(transaction);
393     }
394 
395     /**
396      * Starting on R, actor enforcement and app visibility changes introduce additional failure
397      * cases, but the SecurityException thrown with these checks is unexpected for existing
398      * consumers of the API.
399      *
400      * The only prior case it would be thrown is with a permission failure, but the calling
401      * application would be able to verify that themselves, and so they may choose to ignore
402      * catching SecurityException when calling these APIs.
403      *
404      * For R, this no longer holds true, and SecurityExceptions can be thrown for any number of
405      * reasons, none of which are exposed to the caller. So for consumers targeting below R,
406      * transform these SecurityExceptions into IllegalStateExceptions, which are a little more
407      * expected to be thrown by the setEnabled APIs.
408      *
409      * This will mask the prior permission exception if it applies, but it's assumed that apps
410      * wouldn't call the APIs without the permission on prior versions, and so it's safe to ignore.
411      */
rethrowSecurityException(SecurityException e)412     private void rethrowSecurityException(SecurityException e) {
413         if (!Compatibility.isChangeEnabled(THROW_SECURITY_EXCEPTIONS)) {
414             throw new IllegalStateException(e);
415         } else {
416             throw e;
417         }
418     }
419 
420     /**
421      * Commit the self-targeting transaction to register or unregister overlays.
422      *
423      * <p>Applications can request OverlayManager to register overlays and unregister the registered
424      * overlays via {@link OverlayManagerTransaction}.
425      *
426      * @throws IOException if there is a file operation error.
427      * @throws PackageManager.NameNotFoundException if the package name is not found.
428      * @hide
429      */
430     @NonUiContext
commitSelfTarget(@onNull final OverlayManagerTransaction transaction)431     void commitSelfTarget(@NonNull final OverlayManagerTransaction transaction)
432             throws PackageManager.NameNotFoundException, IOException {
433         synchronized (mOverlayManagerImpl) {
434             mOverlayManagerImpl.commit(transaction);
435         }
436     }
437 
438     /**
439      * Get the related information of self-targeting overlays for {@code targetPackageName}.
440      *
441      * @param targetPackageName the target package name
442      * @return a list of overlay information
443      */
444     @NonNull
445     @NonUiContext
getOverlayInfosForTarget(@onNull final String targetPackageName)446     public List<OverlayInfo> getOverlayInfosForTarget(@NonNull final String targetPackageName) {
447         synchronized (mOverlayManagerImpl) {
448             return mOverlayManagerImpl.getOverlayInfosForTarget(targetPackageName);
449         }
450     }
451 }
452