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 Context mContext; 63 private final OverlayManagerImpl mOverlayManagerImpl; 64 65 /** 66 * Pre R a {@link java.lang.SecurityException} would only be thrown by setEnabled APIs (e 67 * .g. {@code #setEnabled(String, boolean, UserHandle)}) for a permission error. 68 * Since R this no longer holds true, and {@link java.lang.SecurityException} can be 69 * thrown for any number of reasons, none of which are exposed to the caller. 70 * 71 * <p>To maintain existing API behavior, if a legacy permission failure or actor enforcement 72 * failure occurs for an app not yet targeting R, coerce it into an {@link 73 * java.lang.IllegalStateException}, which existed in the source prior to R. 74 */ 75 @ChangeId 76 @EnabledSince(targetSdkVersion = Build.VERSION_CODES.R) 77 private static final long THROW_SECURITY_EXCEPTIONS = 147340954; 78 79 /** 80 * Applications can use OverlayManager to create overlays to overlay on itself resources. The 81 * overlay target is itself and the work range is only in caller 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 mContext = context; 140 mService = service; 141 mOverlayManagerImpl = new OverlayManagerImpl(context); 142 } 143 144 /** @hide */ 145 @SuppressLint("ReferencesHidden") OverlayManager(@onNull Context context)146 public OverlayManager(@NonNull Context context) { 147 this(context, IOverlayManager.Stub.asInterface( 148 ServiceManager.getService(Context.OVERLAY_SERVICE))); 149 } 150 151 /** 152 * Request that an overlay package is enabled and any other overlay packages with the same 153 * target package and category are disabled. 154 * 155 * If a set of overlay packages share the same category, single call to this method is 156 * equivalent to multiple calls to {@code #setEnabled(String, boolean, UserHandle)}. 157 * 158 * The caller must pass the actor requirements specified in the class comment. 159 * 160 * @param packageName the name of the overlay package to enable. 161 * @param user The user for which to change the overlay. 162 * 163 * @throws SecurityException when caller is not allowed to enable {@param packageName} 164 * @throws IllegalStateException when enabling fails otherwise 165 * 166 * @hide 167 */ 168 @SystemApi 169 @RequiresPermission(anyOf = { 170 "android.permission.INTERACT_ACROSS_USERS", 171 "android.permission.INTERACT_ACROSS_USERS_FULL" 172 }) setEnabledExclusiveInCategory(@onNull final String packageName, @NonNull UserHandle user)173 public void setEnabledExclusiveInCategory(@NonNull final String packageName, 174 @NonNull UserHandle user) throws SecurityException, IllegalStateException { 175 try { 176 if (!mService.setEnabledExclusiveInCategory(packageName, user.getIdentifier())) { 177 throw new IllegalStateException("setEnabledExclusiveInCategory failed"); 178 } 179 } catch (SecurityException e) { 180 rethrowSecurityException(e); 181 } catch (RemoteException e) { 182 throw e.rethrowFromSystemServer(); 183 } 184 } 185 186 /** 187 * Request that an overlay package is enabled or disabled. 188 * 189 * While {@link #setEnabledExclusiveInCategory(String, UserHandle)} doesn't support disabling 190 * every overlay in a category, this method allows you to disable everything. 191 * 192 * The caller must pass the actor requirements specified in the class comment. 193 * 194 * @param packageName the name of the overlay package to enable. 195 * @param enable {@code false} if the overlay should be turned off. 196 * @param user The user for which to change the overlay. 197 * 198 * @throws SecurityException when caller is not allowed to enable/disable {@param packageName} 199 * @throws IllegalStateException when enabling/disabling fails otherwise 200 * 201 * @hide 202 */ 203 @SystemApi 204 @RequiresPermission(anyOf = { 205 "android.permission.INTERACT_ACROSS_USERS", 206 "android.permission.INTERACT_ACROSS_USERS_FULL" 207 }) setEnabled(@onNull final String packageName, final boolean enable, @NonNull UserHandle user)208 public void setEnabled(@NonNull final String packageName, final boolean enable, 209 @NonNull UserHandle user) throws SecurityException, IllegalStateException { 210 try { 211 if (!mService.setEnabled(packageName, enable, user.getIdentifier())) { 212 throw new IllegalStateException("setEnabled failed"); 213 } 214 } catch (SecurityException e) { 215 rethrowSecurityException(e); 216 } catch (RemoteException e) { 217 throw e.rethrowFromSystemServer(); 218 } 219 } 220 221 /** 222 * Returns information about the overlay with the given package name for 223 * the specified user. 224 * 225 * @param packageName The name of the package. 226 * @param userHandle The user to get the OverlayInfos for. 227 * @return An OverlayInfo object; if no overlays exist with the 228 * requested package name, null is returned. 229 * 230 * @hide 231 */ 232 @SystemApi 233 @Nullable getOverlayInfo(@onNull final String packageName, @NonNull final UserHandle userHandle)234 public OverlayInfo getOverlayInfo(@NonNull final String packageName, 235 @NonNull final UserHandle userHandle) { 236 try { 237 return mService.getOverlayInfo(packageName, userHandle.getIdentifier()); 238 } catch (RemoteException e) { 239 throw e.rethrowFromSystemServer(); 240 } 241 } 242 243 /** 244 * Returns information about the overlay represented by the identifier for the specified user. 245 * 246 * @param overlay the identifier representing the overlay 247 * @param userHandle the user of which to get overlay state info 248 * @return the overlay info or null if the overlay cannot be found 249 * 250 * @hide 251 */ 252 @Nullable getOverlayInfo(@onNull final OverlayIdentifier overlay, @NonNull final UserHandle userHandle)253 public OverlayInfo getOverlayInfo(@NonNull final OverlayIdentifier overlay, 254 @NonNull final UserHandle userHandle) { 255 try { 256 return mService.getOverlayInfoByIdentifier(overlay, userHandle.getIdentifier()); 257 } catch (RemoteException e) { 258 throw e.rethrowFromSystemServer(); 259 } 260 } 261 262 /** 263 * Returns information about all overlays for the given target package for 264 * the specified user. The returned list is ordered according to the 265 * overlay priority with the highest priority at the end of the list. 266 * 267 * @param targetPackageName The name of the target package. 268 * @param user The user to get the OverlayInfos for. 269 * @return A list of OverlayInfo objects; if no overlays exist for the 270 * requested package, an empty list is returned. 271 * 272 * @hide 273 */ 274 @SystemApi 275 @RequiresPermission(anyOf = { 276 "android.permission.INTERACT_ACROSS_USERS", 277 "android.permission.INTERACT_ACROSS_USERS_FULL" 278 }) 279 @NonNull getOverlayInfosForTarget(@onNull final String targetPackageName, @NonNull UserHandle user)280 public List<OverlayInfo> getOverlayInfosForTarget(@NonNull final String targetPackageName, 281 @NonNull UserHandle user) { 282 try { 283 return mService.getOverlayInfosForTarget(targetPackageName, user.getIdentifier()); 284 } catch (RemoteException e) { 285 throw e.rethrowFromSystemServer(); 286 } 287 } 288 289 /** 290 * Clear part of the overlay manager's internal cache of PackageInfo 291 * objects. Only intended for testing. 292 * 293 * @param targetPackageName The name of the target package. 294 * @param user The user to get the OverlayInfos for. 295 * 296 * @hide 297 */ 298 @RequiresPermission(anyOf = { 299 "android.permission.INTERACT_ACROSS_USERS", 300 }) 301 @NonNull invalidateCachesForOverlay(@onNull final String targetPackageName, @NonNull UserHandle user)302 public void invalidateCachesForOverlay(@NonNull final String targetPackageName, 303 @NonNull UserHandle user) { 304 try { 305 mService.invalidateCachesForOverlay(targetPackageName, user.getIdentifier()); 306 } catch (RemoteException e) { 307 throw e.rethrowFromSystemServer(); 308 } 309 } 310 311 /** 312 * Perform a series of requests related to overlay packages. This is an 313 * atomic operation: either all requests were performed successfully and 314 * the changes were propagated to the rest of the system, or at least one 315 * request could not be performed successfully and nothing is changed and 316 * nothing is propagated to the rest of the system. 317 * 318 * @see OverlayManagerTransaction 319 * 320 * @param transaction the series of overlay related requests to perform 321 * @throws Exception if not all the requests could be successfully and 322 * atomically executed 323 * 324 * @hide 325 */ commitToSystemServer(@onNull final OverlayManagerTransaction transaction)326 private void commitToSystemServer(@NonNull final OverlayManagerTransaction transaction) { 327 try { 328 mService.commit(transaction); 329 } catch (RemoteException e) { 330 throw e.rethrowFromSystemServer(); 331 } 332 } 333 334 /** 335 * Commit the overlay manager transaction. 336 * 337 * <p>Applications can register overlays and unregister the registered overlays in an atomic 338 * operation via {@link OverlayManagerTransaction}. 339 * 340 * @see OverlayManagerTransaction 341 * 342 * @param transaction the series of overlay related requests to perform 343 * @throws Exception if not all the requests could be successfully 344 */ commit(@onNull final OverlayManagerTransaction transaction)345 public void commit(@NonNull final OverlayManagerTransaction transaction) { 346 if (transaction.isSelfTargeting() 347 || mService == null 348 || mService.asBinder() == null) { 349 try { 350 commitSelfTarget(transaction); 351 } catch (PackageManager.NameNotFoundException | IOException e) { 352 throw new RuntimeException(e); 353 } 354 return; 355 } 356 357 commitToSystemServer(transaction); 358 } 359 360 /** 361 * Starting on R, actor enforcement and app visibility changes introduce additional failure 362 * cases, but the SecurityException thrown with these checks is unexpected for existing 363 * consumers of the API. 364 * 365 * The only prior case it would be thrown is with a permission failure, but the calling 366 * application would be able to verify that themselves, and so they may choose to ignore 367 * catching SecurityException when calling these APIs. 368 * 369 * For R, this no longer holds true, and SecurityExceptions can be thrown for any number of 370 * reasons, none of which are exposed to the caller. So for consumers targeting below R, 371 * transform these SecurityExceptions into IllegalStateExceptions, which are a little more 372 * expected to be thrown by the setEnabled APIs. 373 * 374 * This will mask the prior permission exception if it applies, but it's assumed that apps 375 * wouldn't call the APIs without the permission on prior versions, and so it's safe to ignore. 376 */ rethrowSecurityException(SecurityException e)377 private void rethrowSecurityException(SecurityException e) { 378 if (!Compatibility.isChangeEnabled(THROW_SECURITY_EXCEPTIONS)) { 379 throw new IllegalStateException(e); 380 } else { 381 throw e; 382 } 383 } 384 385 /** 386 * Commit the self-targeting transaction to register or unregister overlays. 387 * 388 * <p>Applications can request OverlayManager to register overlays and unregister the registered 389 * overlays via {@link OverlayManagerTransaction}. 390 * 391 * @throws IOException if there is a file operation error. 392 * @throws PackageManager.NameNotFoundException if the package name is not found. 393 * @hide 394 */ 395 @NonUiContext commitSelfTarget(@onNull final OverlayManagerTransaction transaction)396 void commitSelfTarget(@NonNull final OverlayManagerTransaction transaction) 397 throws PackageManager.NameNotFoundException, IOException { 398 synchronized (mOverlayManagerImpl) { 399 mOverlayManagerImpl.commit(transaction); 400 } 401 } 402 403 /** 404 * Get the related information of overlays for {@code targetPackageName}. 405 * 406 * @param targetPackageName the target package name 407 * @return a list of overlay information 408 */ 409 @NonNull 410 @NonUiContext getOverlayInfosForTarget(@onNull final String targetPackageName)411 public List<OverlayInfo> getOverlayInfosForTarget(@NonNull final String targetPackageName) { 412 synchronized (mOverlayManagerImpl) { 413 return mOverlayManagerImpl.getOverlayInfosForTarget(targetPackageName); 414 } 415 } 416 } 417