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