diff options
6 files changed, 54 insertions, 9 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index 6a8f3052787b..800977cfc596 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -2042,8 +2042,8 @@ package android.content.om { public class OverlayManager { method @Nullable public android.content.om.OverlayInfo getOverlayInfo(@NonNull String, @NonNull android.os.UserHandle); method @NonNull @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public java.util.List<android.content.om.OverlayInfo> getOverlayInfosForTarget(@NonNull String, @NonNull android.os.UserHandle); - method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public void setEnabled(@NonNull String, boolean, @NonNull android.os.UserHandle); - method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public void setEnabledExclusiveInCategory(@NonNull String, @NonNull android.os.UserHandle); + method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public void setEnabled(@NonNull String, boolean, @NonNull android.os.UserHandle) throws java.lang.IllegalStateException, java.lang.SecurityException; + method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public void setEnabledExclusiveInCategory(@NonNull String, @NonNull android.os.UserHandle) throws java.lang.IllegalStateException, java.lang.SecurityException; } } diff --git a/core/java/android/content/om/OverlayManager.java b/core/java/android/content/om/OverlayManager.java index a2f8886eb7d2..33d17763fb24 100644 --- a/core/java/android/content/om/OverlayManager.java +++ b/core/java/android/content/om/OverlayManager.java @@ -22,7 +22,11 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; +import android.compat.Compatibility; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledAfter; import android.content.Context; +import android.os.Build; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; @@ -40,6 +44,10 @@ public class OverlayManager { private final IOverlayManager mService; private final Context mContext; + @ChangeId + @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q) + private static final long THROW_SECURITY_EXCEPTIONS = 147340954; + /** * Creates a new instance. * @@ -69,6 +77,9 @@ public class OverlayManager { * @param packageName the name of the overlay package to enable. * @param user The user for which to change the overlay. * + * @throws SecurityException when caller is not allowed to enable {@param packageName} + * @throws IllegalStateException when enabling fails otherwise + * * @hide */ @SystemApi @@ -77,11 +88,13 @@ public class OverlayManager { "android.permission.INTERACT_ACROSS_USERS_FULL" }) public void setEnabledExclusiveInCategory(@NonNull final String packageName, - @NonNull UserHandle user) { + @NonNull UserHandle user) throws SecurityException, IllegalStateException { try { if (!mService.setEnabledExclusiveInCategory(packageName, user.getIdentifier())) { throw new IllegalStateException("setEnabledExclusiveInCategory failed"); } + } catch (SecurityException e) { + rethrowSecurityException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -97,6 +110,9 @@ public class OverlayManager { * @param enable {@code false} if the overlay should be turned off. * @param user The user for which to change the overlay. * + * @throws SecurityException when caller is not allowed to enable/disable {@param packageName} + * @throws IllegalStateException when enabling/disabling fails otherwise + * * @hide */ @SystemApi @@ -105,15 +121,16 @@ public class OverlayManager { "android.permission.INTERACT_ACROSS_USERS_FULL" }) public void setEnabled(@NonNull final String packageName, final boolean enable, - @NonNull UserHandle user) { + @NonNull UserHandle user) throws SecurityException, IllegalStateException { try { if (!mService.setEnabled(packageName, enable, user.getIdentifier())) { throw new IllegalStateException("setEnabled failed"); } + } catch (SecurityException e) { + rethrowSecurityException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - return; } /** @@ -187,4 +204,29 @@ public class OverlayManager { throw e.rethrowFromSystemServer(); } } + + /** + * Starting on R, actor enforcement and app visibility changes introduce additional failure + * cases, but the SecurityException thrown with these checks is unexpected for existing + * consumers of the API. + * + * The only prior case it would be thrown is with a permission failure, but the calling + * application would be able to verify that themselves, and so they may choose to ignore + * catching SecurityException when calling these APIs. + * + * For R, this no longer holds true, and SecurityExceptions can be thrown for any number of + * reasons, none of which are exposed to the caller. So for consumers targeting below R, + * transform these SecurityExceptions into IllegalStateExceptions, which are a little more + * expected to be thrown by the setEnabled APIs. + * + * This will mask the prior permission exception if it applies, but it's assumed that apps + * wouldn't call the APIs without the permission on prior versions, and so it's safe to ignore. + */ + private void rethrowSecurityException(SecurityException e) { + if (!Compatibility.isChangeEnabled(THROW_SECURITY_EXCEPTIONS)) { + throw new IllegalStateException(e); + } else { + throw e; + } + } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 486386f3d284..107207638205 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -4488,7 +4488,7 @@ public class SettingsProvider extends ContentProvider { try { overlayManager.setEnabledExclusiveInCategory( NAV_BAR_MODE_2BUTTON_OVERLAY, UserHandle.USER_CURRENT); - } catch (RemoteException e) { + } catch (SecurityException | IllegalStateException | RemoteException e) { throw new IllegalStateException( "Failed to set nav bar interaction mode overlay"); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java index d6336ed3e18a..826af669cb39 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java @@ -387,7 +387,7 @@ public class NavigationModeController implements Dumpable { Log.d(TAG, "setModeOverlay: overlayPackage=" + overlayPkg + " userId=" + userId); } - } catch (RemoteException e) { + } catch (SecurityException | IllegalStateException | RemoteException e) { Log.e(TAG, "Failed to enable overlay " + overlayPkg + " for user " + userId); } }); diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java index 41e026af7c72..665cb6307b6a 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java @@ -178,7 +178,7 @@ class ThemeOverlayManager { } else { mOverlayManager.setEnabled(pkg, false, userHandle); } - } catch (IllegalStateException e) { + } catch (SecurityException | IllegalStateException e) { Log.e(TAG, String.format("setEnabled failed: %s %s %b", pkg, userHandle, enabled), e); } diff --git a/services/core/java/com/android/server/om/OverlayActorEnforcer.java b/services/core/java/com/android/server/om/OverlayActorEnforcer.java index ac3bf9ad5d8a..0a9f923ac817 100644 --- a/services/core/java/com/android/server/om/OverlayActorEnforcer.java +++ b/services/core/java/com/android/server/om/OverlayActorEnforcer.java @@ -43,6 +43,9 @@ import java.util.Map; */ public class OverlayActorEnforcer { + // By default, the reason is not logged to prevent leaks of why it failed + private static final boolean DEBUG_REASON = false; + private final VerifyCallback mVerifyCallback; /** @@ -92,7 +95,7 @@ public class OverlayActorEnforcer { throw new SecurityException("UID" + callingUid + " is not allowed to call " + methodName + " for " + (TextUtils.isEmpty(targetOverlayableName) ? "" : (targetOverlayableName + " in ")) - + overlayInfo.targetPackageName + " because " + actorState + + overlayInfo.targetPackageName + (DEBUG_REASON ? (" because " + actorState) : "") ); } |