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.Nullable;
21 import android.annotation.RequiresPermission;
22 import android.annotation.SystemApi;
23 import android.annotation.SystemService;
24 import android.compat.Compatibility;
25 import android.compat.annotation.ChangeId;
26 import android.compat.annotation.EnabledSince;
27 import android.content.Context;
28 import android.os.Build;
29 import android.os.Process;
30 import android.os.RemoteException;
31 import android.os.ServiceManager;
32 import android.os.UserHandle;
33 
34 import com.android.server.SystemConfig;
35 
36 import java.util.List;
37 
38 /**
39  * Updates OverlayManager state; gets information about installed overlay packages.
40  *
41  * <p>Users of this API must be actors of any overlays they desire to change the state of.</p>
42  *
43  * <p>An actor is a package responsible for managing the state of overlays targeting overlayables
44  * that specify the actor. For example, an actor may enable or disable an overlay or otherwise
45  * change its state.</p>
46  *
47  * <p>Actors are specified as part of the overlayable definition.
48  *
49  * <pre>{@code
50  * <overlayable name="OverlayableResourcesName" actor="overlay://namespace/actorName">
51  * }</pre></p>
52  *
53  * <p>Actors are defined through {@link SystemConfig}. Only system packages can be used.
54  * The namespace "android" is reserved for use by AOSP and any "android" definitions must
55  * have an implementation on device that fulfill their intended functionality.</p>
56  *
57  * <pre>{@code
58  * <named-actor
59  *     namespace="namespace"
60  *     name="actorName"
61  *     package="com.example.pkg"
62  *     />
63  * }</pre></p>
64  *
65  * <p>An actor can manipulate a particular overlay if any of the following is true:
66  * <ul>
67  * <li>its UID is {@link Process#ROOT_UID}, {@link Process#SYSTEM_UID}</li>
68  * <li>it is the target of the overlay package</li>
69  * <li>it has the CHANGE_OVERLAY_PACKAGES permission and the target does not specify an actor</li>
70  * <li>it is the actor specified by the overlayable</li>
71  * </ul></p>
72  *
73  * @hide
74  */
75 @SystemApi
76 @SystemService(Context.OVERLAY_SERVICE)
77 public class OverlayManager {
78 
79     private final IOverlayManager mService;
80     private final Context mContext;
81 
82     /**
83      * Pre R a {@link java.lang.SecurityException} would only be thrown by setEnabled APIs (e
84      * .g. {@link #setEnabled(String, boolean, UserHandle)}) for a permission error.
85      * Since R this no longer holds true, and {@link java.lang.SecurityException} can be
86      * thrown for any number of reasons, none of which are exposed to the caller.
87      *
88      * <p>To maintain existing API behavior, if a legacy permission failure or actor enforcement
89      * failure occurs for an app not yet targeting R, coerce it into an {@link
90      * java.lang.IllegalStateException}, which existed in the source prior to R.
91      */
92     @ChangeId
93     @EnabledSince(targetSdkVersion = Build.VERSION_CODES.R)
94     private static final long THROW_SECURITY_EXCEPTIONS = 147340954;
95 
96     /**
97      * Creates a new instance.
98      *
99      * @param context The current context in which to operate.
100      * @param service The backing system service.
101      *
102      * @hide
103      */
OverlayManager(Context context, IOverlayManager service)104     public OverlayManager(Context context, IOverlayManager service) {
105         mContext = context;
106         mService = service;
107     }
108 
109     /** @hide */
OverlayManager(Context context)110     public OverlayManager(Context context) {
111         this(context, IOverlayManager.Stub.asInterface(
112             ServiceManager.getService(Context.OVERLAY_SERVICE)));
113     }
114 
115     /**
116      * Request that an overlay package is enabled and any other overlay packages with the same
117      * target package and category are disabled.
118      *
119      * If a set of overlay packages share the same category, single call to this method is
120      * equivalent to multiple calls to {@link #setEnabled(String, boolean, UserHandle)}.
121      *
122      * The caller must pass the actor requirements specified in the class comment.
123      *
124      * @param packageName the name of the overlay package to enable.
125      * @param user The user for which to change the overlay.
126      *
127      * @throws SecurityException when caller is not allowed to enable {@param packageName}
128      * @throws IllegalStateException when enabling fails otherwise
129      *
130      * @hide
131      */
132     @SystemApi
133     @RequiresPermission(anyOf = {
134             "android.permission.INTERACT_ACROSS_USERS",
135             "android.permission.INTERACT_ACROSS_USERS_FULL"
136     })
setEnabledExclusiveInCategory(@onNull final String packageName, @NonNull UserHandle user)137     public void setEnabledExclusiveInCategory(@NonNull final String packageName,
138             @NonNull UserHandle user) throws SecurityException, IllegalStateException {
139         try {
140             if (!mService.setEnabledExclusiveInCategory(packageName, user.getIdentifier())) {
141                 throw new IllegalStateException("setEnabledExclusiveInCategory failed");
142             }
143         } catch (SecurityException e) {
144             rethrowSecurityException(e);
145         } catch (RemoteException e) {
146             throw e.rethrowFromSystemServer();
147         }
148     }
149 
150     /**
151      * Request that an overlay package is enabled or disabled.
152      *
153      * While {@link #setEnabledExclusiveInCategory(String, UserHandle)} doesn't support disabling
154      * every overlay in a category, this method allows you to disable everything.
155      *
156      * The caller must pass the actor requirements specified in the class comment.
157      *
158      * @param packageName the name of the overlay package to enable.
159      * @param enable {@code false} if the overlay should be turned off.
160      * @param user The user for which to change the overlay.
161      *
162      * @throws SecurityException when caller is not allowed to enable/disable {@param packageName}
163      * @throws IllegalStateException when enabling/disabling 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     })
setEnabled(@onNull final String packageName, final boolean enable, @NonNull UserHandle user)172     public void setEnabled(@NonNull final String packageName, final boolean enable,
173             @NonNull UserHandle user) throws SecurityException, IllegalStateException {
174         try {
175             if (!mService.setEnabled(packageName, enable, user.getIdentifier())) {
176                 throw new IllegalStateException("setEnabled failed");
177             }
178         } catch (SecurityException e) {
179             rethrowSecurityException(e);
180         } catch (RemoteException e) {
181             throw e.rethrowFromSystemServer();
182         }
183     }
184 
185     /**
186      * Returns information about the overlay with the given package name for
187      * the specified user.
188      *
189      * @param packageName The name of the package.
190      * @param userHandle The user to get the OverlayInfos for.
191      * @return An OverlayInfo object; if no overlays exist with the
192      *         requested package name, null is returned.
193      *
194      * @hide
195      */
196     @SystemApi
197     @Nullable
getOverlayInfo(@onNull final String packageName, @NonNull final UserHandle userHandle)198     public OverlayInfo getOverlayInfo(@NonNull final String packageName,
199             @NonNull final UserHandle userHandle) {
200         try {
201             return mService.getOverlayInfo(packageName, userHandle.getIdentifier());
202         } catch (RemoteException e) {
203             throw e.rethrowFromSystemServer();
204         }
205     }
206 
207     /**
208      * Returns information about the overlay represented by the identifier for the specified user.
209      *
210      * @param overlay the identifier representing the overlay
211      * @param userHandle the user of which to get overlay state info
212      * @return the overlay info or null if the overlay cannot be found
213      *
214      * @hide
215      */
216     @Nullable
getOverlayInfo(@onNull final OverlayIdentifier overlay, @NonNull final UserHandle userHandle)217     public OverlayInfo getOverlayInfo(@NonNull final OverlayIdentifier overlay,
218             @NonNull final UserHandle userHandle) {
219         try {
220             return mService.getOverlayInfoByIdentifier(overlay, userHandle.getIdentifier());
221         } catch (RemoteException e) {
222             throw e.rethrowFromSystemServer();
223         }
224     }
225 
226     /**
227      * Returns information about all overlays for the given target package for
228      * the specified user. The returned list is ordered according to the
229      * overlay priority with the highest priority at the end of the list.
230      *
231      * @param targetPackageName The name of the target package.
232      * @param user The user to get the OverlayInfos for.
233      * @return A list of OverlayInfo objects; if no overlays exist for the
234      *         requested package, an empty list is returned.
235      *
236      * @hide
237      */
238     @SystemApi
239     @RequiresPermission(anyOf = {
240             "android.permission.INTERACT_ACROSS_USERS",
241             "android.permission.INTERACT_ACROSS_USERS_FULL"
242     })
243     @NonNull
getOverlayInfosForTarget(@onNull final String targetPackageName, @NonNull UserHandle user)244     public List<OverlayInfo> getOverlayInfosForTarget(@NonNull final String targetPackageName,
245             @NonNull UserHandle user) {
246         try {
247             return mService.getOverlayInfosForTarget(targetPackageName, user.getIdentifier());
248         } catch (RemoteException e) {
249             throw e.rethrowFromSystemServer();
250         }
251     }
252 
253     /**
254      * Clear part of the overlay manager's internal cache of PackageInfo
255      * objects. Only intended for testing.
256      *
257      * @param targetPackageName The name of the target package.
258      * @param user The user to get the OverlayInfos for.
259      *
260      * @hide
261      */
262     @RequiresPermission(anyOf = {
263             "android.permission.INTERACT_ACROSS_USERS",
264     })
265     @NonNull
invalidateCachesForOverlay(@onNull final String targetPackageName, @NonNull UserHandle user)266     public void invalidateCachesForOverlay(@NonNull final String targetPackageName,
267             @NonNull UserHandle user) {
268         try {
269             mService.invalidateCachesForOverlay(targetPackageName, user.getIdentifier());
270         } catch (RemoteException e) {
271             throw e.rethrowFromSystemServer();
272         }
273     }
274 
275     /**
276      * Perform a series of requests related to overlay packages. This is an
277      * atomic operation: either all requests were performed successfully and
278      * the changes were propagated to the rest of the system, or at least one
279      * request could not be performed successfully and nothing is changed and
280      * nothing is propagated to the rest of the system.
281      *
282      * @see OverlayManagerTransaction
283      *
284      * @param transaction the series of overlay related requests to perform
285      * @throws Exception if not all the requests could be successfully and
286      *         atomically executed
287      *
288      * @hide
289      */
commit(@onNull final OverlayManagerTransaction transaction)290     public void commit(@NonNull final OverlayManagerTransaction transaction) {
291         try {
292             mService.commit(transaction);
293         } catch (RemoteException e) {
294             throw e.rethrowFromSystemServer();
295         }
296     }
297 
298     /**
299      * Starting on R, actor enforcement and app visibility changes introduce additional failure
300      * cases, but the SecurityException thrown with these checks is unexpected for existing
301      * consumers of the API.
302      *
303      * The only prior case it would be thrown is with a permission failure, but the calling
304      * application would be able to verify that themselves, and so they may choose to ignore
305      * catching SecurityException when calling these APIs.
306      *
307      * For R, this no longer holds true, and SecurityExceptions can be thrown for any number of
308      * reasons, none of which are exposed to the caller. So for consumers targeting below R,
309      * transform these SecurityExceptions into IllegalStateExceptions, which are a little more
310      * expected to be thrown by the setEnabled APIs.
311      *
312      * This will mask the prior permission exception if it applies, but it's assumed that apps
313      * wouldn't call the APIs without the permission on prior versions, and so it's safe to ignore.
314      */
rethrowSecurityException(SecurityException e)315     private void rethrowSecurityException(SecurityException e) {
316         if (!Compatibility.isChangeEnabled(THROW_SECURITY_EXCEPTIONS)) {
317             throw new IllegalStateException(e);
318         } else {
319             throw e;
320         }
321     }
322 }
323