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