diff options
24 files changed, 432 insertions, 353 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index c0da879241ab..282f6f749128 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -3499,9 +3499,9 @@ package android.media { method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.audiopolicy.AudioProductStrategies getAudioProductStrategies(); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.audiopolicy.AudioVolumeGroups getAudioVolumeGroups(); - method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); - method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); - method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); + method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); + method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); + method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); method public boolean isAudioServerRunning(); method public boolean isHdmiSystemAudioSupported(); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int registerAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy); diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index da9ea8359854..926044bffdd0 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -33,7 +33,6 @@ import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.GraphicBuffer; import android.graphics.Rect; -import android.hardware.HardwareBuffer; import android.os.Bundle; import android.os.Handler; import android.os.IRemoteCallback; @@ -925,8 +924,7 @@ public class ActivityOptions { // Unpackage the GraphicBuffer from the parceled thumbnail final GraphicBuffer buffer = opts.getParcelable(KEY_ANIM_THUMBNAIL); if (buffer != null) { - mThumbnail = Bitmap.wrapHardwareBuffer( - HardwareBuffer.createFromGraphicBuffer(buffer), null); + mThumbnail = Bitmap.wrapHardwareBuffer(buffer, null); } mStartX = opts.getInt(KEY_ANIM_START_X, 0); mStartY = opts.getInt(KEY_ANIM_START_Y, 0); diff --git a/core/java/android/app/AppComponentFactory.java b/core/java/android/app/AppComponentFactory.java index 2cec7f0fc323..5b02817b7bfb 100644 --- a/core/java/android/app/AppComponentFactory.java +++ b/core/java/android/app/AppComponentFactory.java @@ -35,11 +35,22 @@ import android.content.pm.ApplicationInfo; public class AppComponentFactory { /** - * Allows application to override the creation of the default class loader. - * This can be used to perform things such as dependency injection or setting up - * a custom class loader hierarchy. + * Selects the class loader which will be used by the platform to instantiate app components. + * <p> + * The default implementation of this method returns the {@code cl} parameter unchanged. + * Applications can override this method to set up a custom class loader or a custom class + * loader hierarchy and return it to the platform. + * <p> + * The method is a hook invoked before any application components are instantiated or the + * application Context is initialized. It is intended to allow the application's classes to + * be loaded from a different source than the base/split APK(s). + * <p> + * The default class loader {@code cl} is created by the platform and used to load the + * application's base or split APK(s). Its parent is typically the boot class loader, unless + * running under instrumentation. Its classname is configurable using the + * {@link android.R.attr#classLoader} manifest attribute. * - * @param cl The default classloader instantiated by platform. + * @param cl The default class loader created by the platform. * @param aInfo Information about the application being loaded. */ public @NonNull ClassLoader instantiateClassLoader(@NonNull ClassLoader cl, diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index af738da20621..b97ea5f2a475 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3820,10 +3820,7 @@ public abstract class Context { /** * Use with {@link #getSystemService(String)} to retrieve a {@link - * android.net.wifi.rtt.WifiRttManager} for ranging devices with wifi - * - * Note: this is a replacement for WIFI_RTT_SERVICE above. It will - * be renamed once final implementation in place. + * android.net.wifi.rtt.WifiRttManager} for ranging devices with wifi. * * @see #getSystemService(String) * @see android.net.wifi.rtt.WifiRttManager diff --git a/core/java/android/hardware/biometrics/CryptoObject.java b/core/java/android/hardware/biometrics/CryptoObject.java index 496d9c57f252..787dc6696cd3 100644 --- a/core/java/android/hardware/biometrics/CryptoObject.java +++ b/core/java/android/hardware/biometrics/CryptoObject.java @@ -25,8 +25,8 @@ import javax.crypto.Cipher; import javax.crypto.Mac; /** - * A wrapper class for the crypto objects supported by FingerprintManager. Currently the - * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects. + * A wrapper class for the crypto objects supported by BiometricPrompt and FingerprintManager. + * Currently the framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects. * @hide */ public class CryptoObject { diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index e3b2d898f9b6..6326f2e6b2bb 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1075,6 +1075,22 @@ public final class Settings { "android.settings.ADD_ACCOUNT_SETTINGS"; /** + * Activity Action: Show settings for enabling or disabling data saver + * <p></p> + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + * + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_DATA_SAVER_SETTINGS = + "android.settings.DATA_SAVER_SETTINGS"; + + /** * Activity Action: Show settings for selecting the network operator. * <p> * In some cases, a matching Activity may not exist, so ensure you diff --git a/core/java/android/service/contentsuggestions/ContentSuggestionsService.java b/core/java/android/service/contentsuggestions/ContentSuggestionsService.java index 45a8466bfca1..55e61410b9e2 100644 --- a/core/java/android/service/contentsuggestions/ContentSuggestionsService.java +++ b/core/java/android/service/contentsuggestions/ContentSuggestionsService.java @@ -31,7 +31,6 @@ import android.app.contentsuggestions.SelectionsRequest; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.GraphicBuffer; -import android.hardware.HardwareBuffer; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -67,8 +66,7 @@ public abstract class ContentSuggestionsService extends Service { Bitmap wrappedBuffer = null; if (contextImage != null) { - wrappedBuffer = Bitmap.wrapHardwareBuffer( - HardwareBuffer.createFromGraphicBuffer(contextImage), null); + wrappedBuffer = Bitmap.wrapHardwareBuffer(contextImage, null); } mHandler.sendMessage( diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 79363edb0955..b5ad908e5ea5 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -41,7 +41,6 @@ import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; -import android.hardware.HardwareBuffer; import android.hardware.display.DisplayedContentSample; import android.hardware.display.DisplayedContentSamplingAttributes; import android.os.Build; @@ -1917,9 +1916,7 @@ public final class SurfaceControl implements Parcelable { Log.w(TAG, "Failed to take screenshot"); return null; } - return Bitmap.wrapHardwareBuffer( - HardwareBuffer.createFromGraphicBuffer(buffer.getGraphicBuffer()), - buffer.getColorSpace()); + return Bitmap.wrapHardwareBuffer(buffer.getGraphicBuffer(), buffer.getColorSpace()); } /** diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java index ef5178aca40a..65a63a05f666 100644 --- a/core/java/com/android/internal/infra/AbstractRemoteService.java +++ b/core/java/com/android/internal/infra/AbstractRemoteService.java @@ -344,13 +344,21 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I * {@link #getTimeoutIdleBindMillis() idle timeout} expires. */ protected void scheduleUnbind() { - final long unbindDelay = getTimeoutIdleBindMillis(); + scheduleUnbind(true); + } + + private void scheduleUnbind(boolean delay) { + long unbindDelay = getTimeoutIdleBindMillis(); - if (unbindDelay <= 0) { + if (unbindDelay <= PERMANENT_BOUND_TIMEOUT_MS) { if (mVerbose) Slog.v(mTag, "not scheduling unbind when value is " + unbindDelay); return; } + if (!delay) { + unbindDelay = 0; + } + cancelScheduledUnbind(); // TODO(b/117779333): make sure it's unbound if the service settings changing (right now // it's not) @@ -462,9 +470,16 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I @Override public void onServiceDisconnected(ComponentName name) { + if (mVerbose) Slog.v(mTag, "onServiceDisconnected()"); mBinding = true; mService = null; } + + @Override + public void onBindingDied(ComponentName name) { + if (mVerbose) Slog.v(mTag, "onBindingDied()"); + scheduleUnbind(false); + } } private boolean checkIfDestroyed() { diff --git a/core/java/com/android/internal/os/RoSystemProperties.java b/core/java/com/android/internal/os/RoSystemProperties.java index 1aef573f5189..b0855f494ffd 100644 --- a/core/java/com/android/internal/os/RoSystemProperties.java +++ b/core/java/com/android/internal/os/RoSystemProperties.java @@ -60,7 +60,7 @@ public class RoSystemProperties { public static final boolean FW_SYSTEM_USER_SPLIT = SystemProperties.getBoolean("ro.fw.system_user_split", false); public static final boolean MULTIUSER_HEADLESS_SYSTEM_USER = - SystemProperties.getBoolean("ro.fw.multiuser.headless_system_user", true); + SystemProperties.getBoolean("ro.fw.multiuser.headless_system_user", false); // ------ ro.crypto.* -------- // public static final CryptoProperties.state_values CRYPTO_STATE = diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 170dec26f361..07f81c18e1ca 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -763,6 +763,18 @@ public final class Bitmap implements Parcelable { } /** + * Utility method to create a hardware backed bitmap using the graphics buffer. + * @hide + */ + @Nullable + public static Bitmap wrapHardwareBuffer(@NonNull GraphicBuffer graphicBuffer, + @Nullable ColorSpace colorSpace) { + try (HardwareBuffer hb = HardwareBuffer.createFromGraphicBuffer(graphicBuffer)) { + return wrapHardwareBuffer(hb, colorSpace); + } + } + + /** * Creates a new bitmap, scaled from an existing bitmap, when possible. If the * specified width and height are the same as the current width and height of * the source bitmap, the source bitmap is returned and no new bitmap is diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index c4df2744eed9..bd6ce7ec6a3b 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -22,7 +22,8 @@ import android.annotation.Nullable; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.app.KeyguardManager; -import android.hardware.fingerprint.FingerprintManager; +import android.hardware.biometrics.BiometricManager; +import android.hardware.biometrics.BiometricPrompt; import android.security.GateKeeper; import android.security.KeyStore; import android.text.TextUtils; @@ -670,9 +671,9 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** - * Returns {@code true} if the key is irreversibly invalidated when a new fingerprint is - * enrolled or all enrolled fingerprints are removed. This has effect only for keys that - * require fingerprint user authentication for every use. + * Returns {@code true} if the key is irreversibly invalidated when a new biometric is + * enrolled or all enrolled biometrics are removed. This has effect only for keys that + * require biometric user authentication for every use. * * @see #isUserAuthenticationRequired() * @see #getUserAuthenticationValidityDurationSeconds() @@ -1098,19 +1099,19 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * <li>The key can only be generated if secure lock screen is set up (see * {@link KeyguardManager#isDeviceSecure()}). Additionally, if the key requires that user * authentication takes place for every use of the key (see - * {@link #setUserAuthenticationValidityDurationSeconds(int)}), at least one fingerprint - * must be enrolled (see {@link FingerprintManager#hasEnrolledFingerprints()}).</li> + * {@link #setUserAuthenticationValidityDurationSeconds(int)}), at least one biometric + * must be enrolled (see {@link BiometricManager#canAuthenticate()}).</li> * <li>The use of the key must be authorized by the user by authenticating to this Android * device using a subset of their secure lock screen credentials such as - * password/PIN/pattern or fingerprint. + * password/PIN/pattern or biometric. * <a href="{@docRoot}training/articles/keystore.html#UserAuthentication">More * information</a>. * <li>The key will become <em>irreversibly invalidated</em> once the secure lock screen is * disabled (reconfigured to None, Swipe or other mode which does not authenticate the user) * or when the secure lock screen is forcibly reset (e.g., by a Device Administrator). * Additionally, if the key requires that user authentication takes place for every use of - * the key, it is also irreversibly invalidated once a new fingerprint is enrolled or once\ - * no more fingerprints are enrolled, unless {@link + * the key, it is also irreversibly invalidated once a new biometric is enrolled or once\ + * no more biometrics are enrolled, unless {@link * #setInvalidatedByBiometricEnrollment(boolean)} is used to allow validity after * enrollment. Attempts to initialize cryptographic operations using such keys will throw * {@link KeyPermanentlyInvalidatedException}.</li> @@ -1121,7 +1122,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * * @see #setUserAuthenticationValidityDurationSeconds(int) * @see KeyguardManager#isDeviceSecure() - * @see FingerprintManager#hasEnrolledFingerprints() + * @see BiometricManager#canAuthenticate() */ @NonNull public Builder setUserAuthenticationRequired(boolean required) { @@ -1161,10 +1162,10 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * the key. * * <p>Cryptographic operations involving keys which require user authentication to take - * place for every operation can only use fingerprint authentication. This is achieved by + * place for every operation can only use biometric authentication. This is achieved by * initializing a cryptographic operation ({@link Signature}, {@link Cipher}, {@link Mac}) - * with the key, wrapping it into a {@link FingerprintManager.CryptoObject}, invoking - * {@code FingerprintManager.authenticate} with {@code CryptoObject}, and proceeding with + * with the key, wrapping it into a {@link BiometricPrompt.CryptoObject}, invoking + * {@code BiometricPrompt.authenticate} with {@code CryptoObject}, and proceeding with * the cryptographic operation only if the authentication flow succeeds. * * <p>Cryptographic operations involving keys which are authorized to be used for a duration @@ -1183,8 +1184,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * for every use of the key. * * @see #setUserAuthenticationRequired(boolean) - * @see FingerprintManager - * @see FingerprintManager.CryptoObject + * @see BiometricPrompt + * @see BiometricPrompt.CryptoObject * @see KeyguardManager */ @NonNull @@ -1286,20 +1287,20 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** - * Sets whether this key should be invalidated on fingerprint enrollment. This + * Sets whether this key should be invalidated on biometric enrollment. This * applies only to keys which require user authentication (see {@link * #setUserAuthenticationRequired(boolean)}) and if no positive validity duration has been * set (see {@link #setUserAuthenticationValidityDurationSeconds(int)}, meaning the key is - * valid for fingerprint authentication only. + * valid for biometric authentication only. * * <p>By default, {@code invalidateKey} is {@code true}, so keys that are valid for - * fingerprint authentication only are <em>irreversibly invalidated</em> when a new - * fingerprint is enrolled, or when all existing fingerprints are deleted. That may be + * biometric authentication only are <em>irreversibly invalidated</em> when a new + * biometric is enrolled, or when all existing biometrics are deleted. That may be * changed by calling this method with {@code invalidateKey} set to {@code false}. * - * <p>Invalidating keys on enrollment of a new finger or unenrollment of all fingers + * <p>Invalidating keys on enrollment of a new biometric or unenrollment of all biometrics * improves security by ensuring that an unauthorized person who obtains the password can't - * gain the use of fingerprint-authenticated keys by enrolling their own finger. However, + * gain the use of biometric-authenticated keys by enrolling their own biometric. However, * invalidating keys makes key-dependent operations impossible, requiring some fallback * procedure to authenticate the user and set up a new key. */ @@ -1322,7 +1323,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * Sets whether the keystore requires the screen to be unlocked before allowing decryption * using this key. If this is set to {@code true}, any attempt to decrypt or sign using this * key while the screen is locked will fail. A locked device requires a PIN, password, - * fingerprint, or other trusted factor to access. While the screen is locked, the key can + * biometric, or other trusted factor to access. While the screen is locked, the key can * still be used for encryption or signature verification. */ @NonNull diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java index 3357fdf46e20..26181a65dc1d 100644 --- a/keystore/java/android/security/keystore/KeyProtection.java +++ b/keystore/java/android/security/keystore/KeyProtection.java @@ -21,12 +21,13 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.app.KeyguardManager; -import android.hardware.fingerprint.FingerprintManager; +import android.hardware.biometrics.BiometricManager; +import android.hardware.biometrics.BiometricPrompt; import android.security.GateKeeper; import java.security.Key; -import java.security.Signature; import java.security.KeyStore.ProtectionParameter; +import java.security.Signature; import java.security.cert.Certificate; import java.util.Date; @@ -479,9 +480,9 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { } /** - * Returns {@code true} if the key is irreversibly invalidated when a new fingerprint is - * enrolled or all enrolled fingerprints are removed. This has effect only for keys that - * require fingerprint user authentication for every use. + * Returns {@code true} if the key is irreversibly invalidated when a new biometric is + * enrolled or all enrolled biometrics are removed. This has effect only for keys that + * require biometric user authentication for every use. * * @see #isUserAuthenticationRequired() * @see #getUserAuthenticationValidityDurationSeconds() @@ -496,7 +497,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { * * Normally an authentication-bound key is tied to the secure user id of the current user * (either the root SID from GateKeeper for auth-bound keys with a timeout, or the authenticator - * id of the current fingerprint set for keys requiring explicit fingerprint authorization). + * id of the current biometric set for keys requiring explicit biometric authorization). * If this parameter is set (this method returning non-zero value), the key should be tied to * the specified secure user id, overriding the logic above. * @@ -762,19 +763,19 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { * <li>The key can only be import if secure lock screen is set up (see * {@link KeyguardManager#isDeviceSecure()}). Additionally, if the key requires that user * authentication takes place for every use of the key (see - * {@link #setUserAuthenticationValidityDurationSeconds(int)}), at least one fingerprint - * must be enrolled (see {@link FingerprintManager#hasEnrolledFingerprints()}).</li> + * {@link #setUserAuthenticationValidityDurationSeconds(int)}), at least one biometric + * must be enrolled (see {@link BiometricManager#canAuthenticate()}).</li> * <li>The use of the key must be authorized by the user by authenticating to this Android * device using a subset of their secure lock screen credentials such as - * password/PIN/pattern or fingerprint. + * password/PIN/pattern or biometric. * <a href="{@docRoot}training/articles/keystore.html#UserAuthentication">More * information</a>. * <li>The key will become <em>irreversibly invalidated</em> once the secure lock screen is * disabled (reconfigured to None, Swipe or other mode which does not authenticate the user) * or when the secure lock screen is forcibly reset (e.g., by a Device Administrator). * Additionally, if the key requires that user authentication takes place for every use of - * the key, it is also irreversibly invalidated once a new fingerprint is enrolled or once\ - * no more fingerprints are enrolled, unless {@link + * the key, it is also irreversibly invalidated once a new biometric is enrolled or once\ + * no more biometrics are enrolled, unless {@link * #setInvalidatedByBiometricEnrollment(boolean)} is used to allow validity after * enrollment. Attempts to initialize cryptographic operations using such keys will throw * {@link KeyPermanentlyInvalidatedException}.</li> </ul> @@ -784,7 +785,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { * * @see #setUserAuthenticationValidityDurationSeconds(int) * @see KeyguardManager#isDeviceSecure() - * @see FingerprintManager#hasEnrolledFingerprints() + * @see BiometricManager#canAuthenticate() */ @NonNull public Builder setUserAuthenticationRequired(boolean required) { @@ -824,10 +825,10 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { * the key. * * <p>Cryptographic operations involving keys which require user authentication to take - * place for every operation can only use fingerprint authentication. This is achieved by + * place for every operation can only use biometric authentication. This is achieved by * initializing a cryptographic operation ({@link Signature}, {@link Cipher}, {@link Mac}) - * with the key, wrapping it into a {@link FingerprintManager.CryptoObject}, invoking - * {@code FingerprintManager.authenticate} with {@code CryptoObject}, and proceeding with + * with the key, wrapping it into a {@link BiometricPrompt.CryptoObject}, invoking + * {@code BiometricPrompt.authenticate} with {@code CryptoObject}, and proceeding with * the cryptographic operation only if the authentication flow succeeds. * * <p>Cryptographic operations involving keys which are authorized to be used for a duration @@ -846,8 +847,8 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { * for every use of the key. * * @see #setUserAuthenticationRequired(boolean) - * @see FingerprintManager - * @see FingerprintManager.CryptoObject + * @see BiometricPrompt + * @see BiometricPrompt.CryptoObject * @see KeyguardManager */ @NonNull @@ -902,20 +903,20 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { } /** - * Sets whether this key should be invalidated on fingerprint enrollment. This + * Sets whether this key should be invalidated on biometric enrollment. This * applies only to keys which require user authentication (see {@link * #setUserAuthenticationRequired(boolean)}) and if no positive validity duration has been * set (see {@link #setUserAuthenticationValidityDurationSeconds(int)}, meaning the key is - * valid for fingerprint authentication only. + * valid for biometric authentication only. * * <p>By default, {@code invalidateKey} is {@code true}, so keys that are valid for - * fingerprint authentication only are <em>irreversibly invalidated</em> when a new - * fingerprint is enrolled, or when all existing fingerprints are deleted. That may be + * biometric authentication only are <em>irreversibly invalidated</em> when a new + * biometric is enrolled, or when all existing biometrics are deleted. That may be * changed by calling this method with {@code invalidateKey} set to {@code false}. * - * <p>Invalidating keys on enrollment of a new finger or unenrollment of all fingers + * <p>Invalidating keys on enrollment of a new biometric or unenrollment of all biometrics * improves security by ensuring that an unauthorized person who obtains the password can't - * gain the use of fingerprint-authenticated keys by enrolling their own finger. However, + * gain the use of biometric-authenticated keys by enrolling their own biometric. However, * invalidating keys makes key-dependent operations impossible, requiring some fallback * procedure to authenticate the user and set up a new key. */ @@ -930,7 +931,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { * * Normally an authentication-bound key is tied to the secure user id of the current user * (either the root SID from GateKeeper for auth-bound keys with a timeout, or the - * authenticator id of the current fingerprint set for keys requiring explicit fingerprint + * authenticator id of the current biometric set for keys requiring explicit biometric * authorization). If this parameter is set (this method returning non-zero value), the key * should be tied to the specified secure user id, overriding the logic above. * @@ -964,7 +965,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { * Sets whether the keystore requires the screen to be unlocked before allowing decryption * using this key. If this is set to {@code true}, any attempt to decrypt or sign using this * key while the screen is locked will fail. A locked device requires a PIN, password, - * fingerprint, or other trusted factor to access. While the screen is locked, the key can + * biometric, or other trusted factor to access. While the screen is locked, the key can * still be used for encryption or signature verification. */ @NonNull diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index dc5c6639375b..a5a409286754 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -17,6 +17,7 @@ package android.media; import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -1204,6 +1205,7 @@ public class AudioManager { * @hide */ @SystemApi + @IntRange(from = 0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getVolumeIndexForAttributes(@NonNull AudioAttributes attr) { Preconditions.checkNotNull(attr, "attr must not be null"); @@ -1224,6 +1226,7 @@ public class AudioManager { * @hide */ @SystemApi + @IntRange(from = 0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull AudioAttributes attr) { Preconditions.checkNotNull(attr, "attr must not be null"); @@ -1244,6 +1247,7 @@ public class AudioManager { * @hide */ @SystemApi + @IntRange(from = 0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull AudioAttributes attr) { Preconditions.checkNotNull(attr, "attr must not be null"); diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java index 1413ac1433f1..98a8110209e6 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java @@ -23,7 +23,6 @@ import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_ import android.app.ActivityManager.TaskSnapshot; import android.graphics.Bitmap; import android.graphics.Rect; -import android.hardware.HardwareBuffer; /** * Data for a single thumbnail. @@ -53,9 +52,7 @@ public class ThumbnailData { } public ThumbnailData(TaskSnapshot snapshot) { - thumbnail = Bitmap.wrapHardwareBuffer( - HardwareBuffer.createFromGraphicBuffer(snapshot.getSnapshot()), - snapshot.getColorSpace()); + thumbnail = Bitmap.wrapHardwareBuffer(snapshot.getSnapshot(), snapshot.getColorSpace()); insets = new Rect(snapshot.getContentInsets()); orientation = snapshot.getOrientation(); reducedResolution = snapshot.isReducedResolution(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index 38962eb14705..20e002edfe02 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -25,6 +25,7 @@ import android.content.Intent; import android.content.res.Resources; import android.provider.Settings; import android.service.quicksettings.Tile; +import android.telephony.SubscriptionManager; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; @@ -285,7 +286,13 @@ public class CellularTile extends QSTileImpl<SignalState> { } static Intent getCellularSettingIntent() { - return new Intent(Settings.ACTION_DATA_USAGE_SETTINGS); + Intent intent = new Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS); + int dataSub = SubscriptionManager.getDefaultDataSubscriptionId(); + if (dataSub != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + intent.putExtra(Settings.EXTRA_SUB_ID, + SubscriptionManager.getDefaultDataSubscriptionId()); + } + return intent; } private final class CellularDetailAdapter implements DetailAdapter { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java index c6c6f877ac9b..79996bcfa808 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java @@ -16,6 +16,7 @@ package com.android.systemui.qs.tiles; import android.content.DialogInterface.OnClickListener; import android.content.Intent; +import android.provider.Settings; import android.service.quicksettings.Tile; import android.widget.Switch; @@ -54,7 +55,7 @@ public class DataSaverTile extends QSTileImpl<BooleanState> implements @Override public Intent getLongClickIntent() { - return CellularTile.getCellularSettingIntent(); + return new Intent(Settings.ACTION_DATA_SAVER_SETTINGS); } @Override protected void handleClick() { diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index c75a462d5bc1..dd63e3ca290e 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -18,12 +18,6 @@ package com.android.server.pm.permission; import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; -import static android.app.AppOpsManager.MODE_ALLOWED; -import static android.app.AppOpsManager.MODE_ERRORED; -import static android.app.AppOpsManager.MODE_FOREGROUND; -import static android.app.AppOpsManager.OP_NONE; -import static android.app.AppOpsManager.permissionToOp; -import static android.app.AppOpsManager.permissionToOpCode; import static android.content.pm.PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT; import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION; import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT; @@ -40,8 +34,6 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_UPGRAD import static android.content.pm.PackageManager.MASK_PERMISSION_FLAGS_ALL; import static android.content.pm.PackageManager.RESTRICTED_PERMISSIONS_ENABLED; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; -import static android.os.UserHandle.getAppId; -import static android.os.UserHandle.getUid; import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL; import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING; @@ -56,8 +48,6 @@ import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; -import android.app.AppOpsManager; -import android.app.AppOpsManagerInternal; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager.PermissionWhitelistFlags; @@ -1309,9 +1299,6 @@ public class PermissionManagerService { updatedUserIds); updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions, permissionsState, pkg, updatedUserIds); - - // TODO: Move to PermissionPolicyService - setAppOpsLocked(permissionsState, pkg); } // Persist the runtime permissions state for users with changes. If permissions @@ -1327,23 +1314,6 @@ public class PermissionManagerService { } /** - * Set app op for a app-op related to a permission. - * - * @param permission The permission the app-op belongs to - * @param pkg The package the permission belongs to - * @param userId The user to be changed - * @param mode The new mode to set - */ - private void setAppOpMode(@NonNull String permission, @NonNull PackageParser.Package pkg, - @UserIdInt int userId, int mode) { - AppOpsManagerInternal appOpsInternal = LocalServices.getService( - AppOpsManagerInternal.class); - - appOpsInternal.setUidMode(permissionToOpCode(permission), - getUid(userId, getAppId(pkg.applicationInfo.uid)), mode); - } - - /** * Revoke permissions that are not implicit anymore and that have * {@link PackageManager#FLAG_PERMISSION_REVOKE_WHEN_REQUESTED} set. * @@ -1357,8 +1327,6 @@ public class PermissionManagerService { private @NonNull int[] revokePermissionsNoLongerImplicitLocked( @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg, @NonNull int[] updatedUserIds) { - AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class); - String pkgName = pkg.packageName; boolean supportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M; @@ -1390,23 +1358,6 @@ public class PermissionManagerService { } flagsToRemove |= USER_PERMISSION_FLAGS; - - List<String> fgPerms = mBackgroundPermissions.get(permission); - if (fgPerms != null) { - int numFgPerms = fgPerms.size(); - for (int fgPermNum = 0; fgPermNum < numFgPerms; fgPermNum++) { - String fgPerm = fgPerms.get(fgPermNum); - - int mode = appOpsManager.unsafeCheckOpRaw( - permissionToOp(fgPerm), - getUid(userId, getAppId(pkg.applicationInfo.uid)), - pkgName); - - if (mode == MODE_ALLOWED) { - setAppOpMode(fgPerm, pkg, userId, MODE_FOREGROUND); - } - } - } } ps.updatePermissionFlags(bp, userId, flagsToRemove, 0); @@ -1438,91 +1389,39 @@ public class PermissionManagerService { @NonNull ArraySet<String> sourcePerms, @NonNull String newPerm, @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg, @UserIdInt int userId) { - AppOpsManagerInternal appOpsManager = LocalServices.getService(AppOpsManagerInternal.class); String pkgName = pkg.packageName; + boolean isGranted = false; + int flags = 0; - if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { - if (permissionToOp(newPerm) != null) { - int mostLenientSourceMode = MODE_ERRORED; - int flags = 0; - - // Find most lenient source permission state. - int numSourcePerms = sourcePerms.size(); - for (int i = 0; i < numSourcePerms; i++) { - String sourcePerm = sourcePerms.valueAt(i); - - if (ps.hasRuntimePermission(sourcePerm, userId)) { - int sourceOp = permissionToOpCode(sourcePerm); - - if (sourceOp != OP_NONE) { - int mode = appOpsManager.checkOperationUnchecked(sourceOp, - getUid(userId, getAppId(pkg.applicationInfo.uid)), pkgName); - - if (mode == MODE_FOREGROUND || mode == MODE_ERRORED) { - Log.wtf(TAG, "split permission" + sourcePerm + " has app-op state " - + AppOpsManager.MODE_NAMES[mode]); - - continue; - } - - // Leniency order: allowed < ignored < default - if (mode < mostLenientSourceMode) { - mostLenientSourceMode = mode; - flags = ps.getPermissionFlags(sourcePerm, userId); - } else if (mode == mostLenientSourceMode) { - flags |= ps.getPermissionFlags(sourcePerm, userId); - } - } - } + int numSourcePerm = sourcePerms.size(); + for (int i = 0; i < numSourcePerm; i++) { + String sourcePerm = sourcePerms.valueAt(i); + if ((ps.hasRuntimePermission(sourcePerm, userId)) + || ps.hasInstallPermission(sourcePerm)) { + if (!isGranted) { + flags = 0; } - if (mostLenientSourceMode != MODE_ERRORED) { - if (DEBUG_PERMISSIONS) { - Slog.i(TAG, newPerm + " inherits app-ops state " + mostLenientSourceMode - + " from " + sourcePerms + " for " + pkgName); - } - - setAppOpMode(newPerm, pkg, userId, mostLenientSourceMode); - - // Add permission flags - ps.updatePermissionFlags(mSettings.getPermission(newPerm), userId, flags, - flags); - } - } - } else { - boolean isGranted = false; - int flags = 0; - - int numSourcePerm = sourcePerms.size(); - for (int i = 0; i < numSourcePerm; i++) { - String sourcePerm = sourcePerms.valueAt(i); - if ((ps.hasRuntimePermission(sourcePerm, userId)) - || ps.hasInstallPermission(sourcePerm)) { - if (!isGranted) { - flags = 0; - } - - isGranted = true; + isGranted = true; + flags |= ps.getPermissionFlags(sourcePerm, userId); + } else { + if (!isGranted) { flags |= ps.getPermissionFlags(sourcePerm, userId); - } else { - if (!isGranted) { - flags |= ps.getPermissionFlags(sourcePerm, userId); - } } } + } - if (isGranted) { - if (DEBUG_PERMISSIONS) { - Slog.i(TAG, newPerm + " inherits runtime perm grant from " + sourcePerms - + " for " + pkgName); - } - - ps.grantRuntimePermission(mSettings.getPermissionLocked(newPerm), userId); + if (isGranted) { + if (DEBUG_PERMISSIONS) { + Slog.i(TAG, newPerm + " inherits runtime perm grant from " + sourcePerms + + " for " + pkgName); } - // Add permission flags - ps.updatePermissionFlags(mSettings.getPermission(newPerm), userId, flags, flags); + ps.grantRuntimePermission(mSettings.getPermissionLocked(newPerm), userId); } + + // Add permission flags + ps.updatePermissionFlags(mSettings.getPermission(newPerm), userId, flags, flags); } /** @@ -1632,48 +1531,6 @@ public class PermissionManagerService { return updatedUserIds; } - /** - * Fix app-op modes for runtime permissions. - * - * @param permsState The state of the permissions of the package - * @param pkg The package information - */ - private void setAppOpsLocked(@NonNull PermissionsState permsState, - @NonNull PackageParser.Package pkg) { - for (int userId : UserManagerService.getInstance().getUserIds()) { - int numPerms = pkg.requestedPermissions.size(); - for (int i = 0; i < numPerms; i++) { - String permission = pkg.requestedPermissions.get(i); - - // For pre-M apps the runtime permission do not store the state - if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { - continue; - } - - PermissionState state = permsState.getRuntimePermissionState(permission, userId); - if (state == null) { - continue; - } - - // Adjust app-op mods for foreground/background permissions. If an package used to - // have both fg and bg permission granted and it lost the bg permission during an - // upgrade the app-op mode should get downgraded to foreground. - if (state.isGranted()) { - BasePermission bp = mSettings.getPermission(permission); - - if (bp != null && bp.perm != null && bp.perm.info != null - && bp.perm.info.backgroundPermission != null) { - PermissionState bgState = permsState.getRuntimePermissionState( - bp.perm.info.backgroundPermission, userId); - - setAppOpMode(permission, pkg, userId, bgState != null && bgState.isGranted() - ? MODE_ALLOWED : MODE_FOREGROUND); - } - } - } - } - } - private boolean isNewPlatformPermissionForPackage(String perm, PackageParser.Package pkg) { boolean allowed = false; final int NP = PackageParser.NEW_PERMISSIONS.length; diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java index 67f30dc2e9fc..1fd8b711d348 100644 --- a/services/core/java/com/android/server/policy/PermissionPolicyService.java +++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java @@ -17,8 +17,10 @@ package com.android.server.policy; import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION; +import static android.content.pm.PackageManager.GET_PERMISSIONS; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.AppOpsManager; import android.content.Context; @@ -29,6 +31,7 @@ import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal.PackageListObserver; import android.content.pm.PackageParser; import android.content.pm.PermissionInfo; +import android.os.Build; import android.os.Process; import android.os.UserHandle; import android.permission.PermissionControllerManager; @@ -158,37 +161,59 @@ public final class PermissionPolicyService extends SystemService { }); } + private static @Nullable Context getUserContext(@NonNull Context context, + @NonNull UserHandle user) { + if (context.getUser().equals(user)) { + return context; + } else { + try { + return context.createPackageContextAsUser(context.getPackageName(), 0, user); + } catch (NameNotFoundException e) { + Slog.e(LOG_TAG, "Cannot create context for user " + user, e); + return null; + } + } + } + + /** + * Synchronize a single package. + */ private static void synchronizePackagePermissionsAndAppOpsForUser(@NonNull Context context, @NonNull String packageName, @UserIdInt int userId) { final PackageManagerInternal packageManagerInternal = LocalServices.getService( PackageManagerInternal.class); - final PackageParser.Package pkg = packageManagerInternal.getPackage(packageName); + final PackageInfo pkg = packageManagerInternal.getPackageInfo(packageName, 0, + Process.SYSTEM_UID, userId); if (pkg == null) { return; } - final PermissionToOpSynchroniser synchroniser = new PermissionToOpSynchroniser(context); - synchroniser.addPackage(context, pkg, userId); + final PermissionToOpSynchroniser synchroniser = new PermissionToOpSynchroniser( + getUserContext(context, UserHandle.of(userId))); + synchroniser.addPackage(pkg.packageName); final String[] sharedPkgNames = packageManagerInternal.getPackagesForSharedUserId( - pkg.mSharedUserId, userId); + pkg.sharedUserId, userId); if (sharedPkgNames != null) { for (String sharedPkgName : sharedPkgNames) { final PackageParser.Package sharedPkg = packageManagerInternal .getPackage(sharedPkgName); if (sharedPkg != null) { - synchroniser.addPackage(context, sharedPkg, userId); + synchroniser.addPackage(sharedPkg.packageName); } } } synchroniser.syncPackages(); } + /** + * Synchronize all packages + */ private static void synchronizePermissionsAndAppOpsForUser(@NonNull Context context, @UserIdInt int userId) { final PackageManagerInternal packageManagerInternal = LocalServices.getService( PackageManagerInternal.class); - final PermissionToOpSynchroniser synchronizer = new PermissionToOpSynchroniser(context); - packageManagerInternal.forEachPackage((pkg) -> - synchronizer.addPackage(context, pkg, userId)); + final PermissionToOpSynchroniser synchronizer = new PermissionToOpSynchroniser( + getUserContext(context, UserHandle.of(userId))); + packageManagerInternal.forEachPackage((pkg) -> synchronizer.addPackage(pkg.packageName)); synchronizer.syncPackages(); } @@ -198,17 +223,47 @@ public final class PermissionPolicyService extends SystemService { */ private static class PermissionToOpSynchroniser { private final @NonNull Context mContext; - - private final @NonNull SparseIntArray mUids = new SparseIntArray(); - private final @NonNull SparseArray<String> mPackageNames = new SparseArray<>(); - private final @NonNull SparseIntArray mAllowedUidOps = new SparseIntArray(); - private final @NonNull SparseIntArray mDefaultUidOps = new SparseIntArray(); + private final @NonNull PackageManager mPackageManager; + private final @NonNull AppOpsManager mAppOpsManager; + + /** All uid that need to be synchronized */ + private final @NonNull SparseIntArray mAllUids = new SparseIntArray(); + + /** + * All ops that need to be restricted + * + * @see #syncRestrictedOps + */ + private final @NonNull ArrayList<OpToRestrict> mOpsToRestrict = new ArrayList<>(); + + /** + * All ops that need to be unrestricted + * + * @see #syncRestrictedOps + */ + private final @NonNull ArrayList<OpToUnrestrict> mOpsToUnrestrict = new ArrayList<>(); + + /** + * All foreground permissions + * + * @see #syncOpsOfFgPermissions() + */ + private final @NonNull ArrayList<FgPermission> mFgPermOps = new ArrayList<>(); PermissionToOpSynchroniser(@NonNull Context context) { mContext = context; + mPackageManager = context.getPackageManager(); + mAppOpsManager = context.getSystemService(AppOpsManager.class); } - void syncPackages() { + /** + * Set app ops that belong to restricted permissions. + * + * <p>This processes ops previously added by {@link #addOpIfRestricted} + */ + private void syncRestrictedOps() { + final SparseIntArray unprocessedUids = mAllUids.clone(); + // TRICKY: we set the app op for a restricted permission to allow if the app // requesting the permission is whitelisted and to deny if the app requesting // the permission is not whitelisted. However, there is another case where an @@ -222,52 +277,48 @@ public final class PermissionPolicyService extends SystemService { final SparseArray<List<String>> unrequestedRestrictedPermissionsForUid = new SparseArray<>(); - final AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class); - final int allowedCount = mAllowedUidOps.size(); - for (int i = 0; i < allowedCount; i++) { - final int opCode = mAllowedUidOps.keyAt(i); - final int uid = mAllowedUidOps.valueAt(i); - final String packageName = mPackageNames.valueAt(i); - setUidModeAllowed(appOpsManager, opCode, uid, packageName); + final int unrestrictCount = mOpsToUnrestrict.size(); + for (int i = 0; i < unrestrictCount; i++) { + final OpToUnrestrict op = mOpsToUnrestrict.get(i); + setUidModeAllowed(op.code, op.uid, op.packageName); // Keep track this permission was requested by the UID. List<String> unrequestedRestrictedPermissions = - unrequestedRestrictedPermissionsForUid.get(uid); + unrequestedRestrictedPermissionsForUid.get(op.uid); if (unrequestedRestrictedPermissions == null) { unrequestedRestrictedPermissions = new ArrayList<>(sAllRestrictedPermissions); - unrequestedRestrictedPermissionsForUid.put(uid, + unrequestedRestrictedPermissionsForUid.put(op.uid, unrequestedRestrictedPermissions); } - unrequestedRestrictedPermissions.remove(AppOpsManager.opToPermission(opCode)); + unrequestedRestrictedPermissions.remove(AppOpsManager.opToPermission(op.code)); - mUids.delete(uid); + unprocessedUids.delete(op.uid); } - final int defaultCount = mDefaultUidOps.size(); - for (int i = 0; i < defaultCount; i++) { - final int opCode = mDefaultUidOps.keyAt(i); - final int uid = mDefaultUidOps.valueAt(i); - setUidModeDefault(appOpsManager, opCode, uid); + final int restrictCount = mOpsToRestrict.size(); + for (int i = 0; i < restrictCount; i++) { + final OpToRestrict op = mOpsToRestrict.get(i); + setUidModeDefault(op.code, op.uid); // Keep track this permission was requested by the UID. List<String> unrequestedRestrictedPermissions = - unrequestedRestrictedPermissionsForUid.get(uid); + unrequestedRestrictedPermissionsForUid.get(op.uid); if (unrequestedRestrictedPermissions == null) { unrequestedRestrictedPermissions = new ArrayList<>(sAllRestrictedPermissions); - unrequestedRestrictedPermissionsForUid.put(uid, + unrequestedRestrictedPermissionsForUid.put(op.uid, unrequestedRestrictedPermissions); } - unrequestedRestrictedPermissions.remove(AppOpsManager.opToPermission(opCode)); + unrequestedRestrictedPermissions.remove(AppOpsManager.opToPermission(op.code)); - mUids.delete(uid); + unprocessedUids.delete(op.uid); } // Give root access - mUids.put(Process.ROOT_UID, Process.ROOT_UID); + unprocessedUids.put(Process.ROOT_UID, Process.ROOT_UID); // Add records for UIDs that don't use any restricted permissions. - final int uidCount = mUids.size(); + final int uidCount = unprocessedUids.size(); for (int i = 0; i < uidCount; i++) { - final int uid = mUids.keyAt(i); + final int uid = unprocessedUids.keyAt(i); unrequestedRestrictedPermissionsForUid.put(uid, new ArrayList<>(sAllRestrictedPermissions)); } @@ -280,7 +331,7 @@ public final class PermissionPolicyService extends SystemService { if (unrequestedRestrictedPermissions != null) { final int uid = unrequestedRestrictedPermissionsForUid.keyAt(i); final String[] packageNames = (uid != Process.ROOT_UID) - ? mContext.getPackageManager().getPackagesForUid(uid) + ? mPackageManager.getPackagesForUid(uid) : new String[] {"root"}; if (packageNames == null) { continue; @@ -289,8 +340,7 @@ public final class PermissionPolicyService extends SystemService { for (int j = 0; j < permissionCount; j++) { final String permission = unrequestedRestrictedPermissions.get(j); for (String packageName : packageNames) { - setUidModeAllowed(appOpsManager, - AppOpsManager.permissionToOpCode(permission), uid, + setUidModeAllowed(AppOpsManager.permissionToOpCode(permission), uid, packageName); } } @@ -298,19 +348,115 @@ public final class PermissionPolicyService extends SystemService { } } - private void addPackage(@NonNull Context context, - @NonNull PackageParser.Package pkg, @UserIdInt int userId) { - final PackageManager packageManager = context.getPackageManager(); + /** + * Set app ops that belong to restricted permissions. + * + * <p>This processed ops previously added by {@link #addOpIfRestricted} + */ + private void syncOpsOfFgPermissions() { + int numFgPermOps = mFgPermOps.size(); + for (int i = 0; i < numFgPermOps; i++) { + FgPermission perm = mFgPermOps.get(i); + + if (mPackageManager.checkPermission(perm.fgPermissionName, perm.packageName) + == PackageManager.PERMISSION_GRANTED) { + if (mPackageManager.checkPermission(perm.bgPermissionName, perm.packageName) + == PackageManager.PERMISSION_GRANTED) { + mAppOpsManager.setUidMode( + AppOpsManager.permissionToOpCode(perm.fgPermissionName), perm.uid, + AppOpsManager.MODE_ALLOWED); + } else { + mAppOpsManager.setUidMode( + AppOpsManager.permissionToOpCode(perm.fgPermissionName), perm.uid, + AppOpsManager.MODE_FOREGROUND); + } + } else { + mAppOpsManager.setUidMode( + AppOpsManager.permissionToOpCode(perm.fgPermissionName), perm.uid, + AppOpsManager.MODE_IGNORED); + } + } + } + + /** + * Synchronize all previously {@link #addPackage added} packages. + */ + void syncPackages() { + syncRestrictedOps(); + syncOpsOfFgPermissions(); + } + + /** + * Add op that belong to a restricted permission for later processing in + * {@link #syncRestrictedOps}. + * + * <p>Note: Called with the package lock held. Do <u>not</u> call into app-op manager. + * + * @param permissionInfo The permission that is currently looked at + * @param pkg The package looked at + */ + private void addOpIfRestricted(@NonNull PermissionInfo permissionInfo, + @NonNull PackageInfo pkg) { + final String permission = permissionInfo.name; + final int opCode = AppOpsManager.permissionToOpCode(permission); + final int uid = pkg.applicationInfo.uid; + + if (!permissionInfo.isRestricted()) { + return; + } + + final boolean applyRestriction = PackageManager.RESTRICTED_PERMISSIONS_ENABLED + && (mPackageManager.getPermissionFlags(permission, pkg.packageName, + mContext.getUser()) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0; + + if (permissionInfo.isHardRestricted()) { + if (applyRestriction) { + mOpsToRestrict.add(new OpToRestrict(uid, opCode)); + } else { + mOpsToUnrestrict.add(new OpToUnrestrict(uid, pkg.packageName, opCode)); + } + } else if (permissionInfo.isSoftRestricted()) { + //TODO: Implement soft restrictions like storage here. + } + } + + private void addOpIfFgPermissions(@NonNull PermissionInfo permissionInfo, + @NonNull PackageInfo pkg) { + if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { + // Pre-M apps do not store their fg/bg state in the permissions + return; + } + + if (permissionInfo.backgroundPermission == null) { + return; + } - final int uid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.applicationInfo.uid)); - final UserHandle userHandle = UserHandle.of(userId); + mFgPermOps.add(new FgPermission(pkg.applicationInfo.uid, pkg.packageName, + permissionInfo.name, permissionInfo.backgroundPermission)); + } + + /** + * Add a package for {@link #syncPackages() processing} later. + * + * <p>Note: Called with the package lock held. Do <u>not</u> call into app-op manager. + * + * @param pkgName The package to add for later processing. + */ + void addPackage(@NonNull String pkgName) { + final PackageInfo pkg; + try { + pkg = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS); + } catch (NameNotFoundException e) { + return; + } - mUids.put(uid, uid); + mAllUids.put(pkg.applicationInfo.uid, pkg.applicationInfo.uid); - final int permissionCount = pkg.requestedPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - final String permission = pkg.requestedPermissions.get(i); + if (pkg.requestedPermissions == null) { + return; + } + for (String permission : pkg.requestedPermissions) { final int opCode = AppOpsManager.permissionToOpCode(permission); if (opCode == AppOpsManager.OP_NONE) { continue; @@ -318,44 +464,63 @@ public final class PermissionPolicyService extends SystemService { final PermissionInfo permissionInfo; try { - permissionInfo = packageManager.getPermissionInfo(permission, 0); + permissionInfo = mPackageManager.getPermissionInfo(permission, 0); } catch (PackageManager.NameNotFoundException e) { continue; } - if (!permissionInfo.isRestricted()) { - continue; - } - - final boolean applyRestriction = PackageManager.RESTRICTED_PERMISSIONS_ENABLED - && (packageManager.getPermissionFlags(permission, pkg.packageName, - userHandle) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0; - - if (permissionInfo.isHardRestricted()) { - if (applyRestriction) { - mDefaultUidOps.put(opCode, uid); - } else { - mPackageNames.put(opCode, pkg.packageName); - mAllowedUidOps.put(opCode, uid); - } - } else if (permissionInfo.isSoftRestricted()) { - //TODO: Implement soft restrictions like storage here. - } + addOpIfRestricted(permissionInfo, pkg); + addOpIfFgPermissions(permissionInfo, pkg); } } - private static void setUidModeAllowed(@NonNull AppOpsManager appOpsManager, - int opCode, int uid, @NonNull String packageName) { - final int currentMode = appOpsManager.unsafeCheckOpRaw(AppOpsManager + private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) { + final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager .opToPublicName(opCode), uid, packageName); if (currentMode == AppOpsManager.MODE_DEFAULT) { - appOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_ALLOWED); + mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_ALLOWED); } } - private static void setUidModeDefault(@NonNull AppOpsManager appOpsManager, - int opCode, int uid) { - appOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_DEFAULT); + private void setUidModeDefault(int opCode, int uid) { + mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_DEFAULT); + } + + private class OpToRestrict { + final int uid; + final int code; + + OpToRestrict(int uid, int code) { + this.uid = uid; + this.code = code; + } + } + + private class OpToUnrestrict { + final int uid; + final @NonNull String packageName; + final int code; + + OpToUnrestrict(int uid, @NonNull String packageName, int code) { + this.uid = uid; + this.packageName = packageName; + this.code = code; + } + } + + private class FgPermission { + final int uid; + final @NonNull String packageName; + final @NonNull String fgPermissionName; + final @NonNull String bgPermissionName; + + private FgPermission(int uid, @NonNull String packageName, + @NonNull String fgPermissionName, @NonNull String bgPermissionName) { + this.uid = uid; + this.packageName = packageName; + this.fgPermissionName = fgPermissionName; + this.bgPermissionName = bgPermissionName; + } } } } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 6cf36d692520..ed3ec94ea3dd 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -87,6 +87,7 @@ import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET; import static android.os.Build.VERSION_CODES.HONEYCOMB; import static android.os.Build.VERSION_CODES.O; import static android.os.Process.SYSTEM_UID; +import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; @@ -1948,14 +1949,20 @@ final class ActivityRecord extends ConfigurationContainer { return false; } + // Whether the activity is on the sleeping display. + // TODO(b/129750406): This should be applied for the default display, too. + final boolean isDisplaySleeping = getDisplay().isSleeping() + && getDisplayId() != DEFAULT_DISPLAY; // Whether this activity is the top activity of this stack. final boolean isTop = this == stack.getTopActivity(); // Exclude the case where this is the top activity in a pinned stack. final boolean isTopNotPinnedStack = stack.isAttached() && stack.getDisplay().isTopNotPinnedStack(stack); - // Now check whether it's really visible depending on Keyguard state. - return stack.checkKeyguardVisibility(this, + // Now check whether it's really visible depending on Keyguard state, and update + // {@link ActivityStack} internal states. + final boolean visibleIgnoringDisplayStatus = stack.checkKeyguardVisibility(this, visibleIgnoringKeyguard, isTop && isTopNotPinnedStack); + return visibleIgnoringDisplayStatus && !isDisplaySleeping; } boolean shouldBeVisible() { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 0f4e123923b0..ee4e33e4cfaa 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -250,8 +250,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // on the IME target. We mainly have this container grouping so we can keep track of all the IME // window containers together and move them in-sync if/when needed. We use a subclass of // WindowContainer which is omitted from screen magnification, as the IME is never magnified. - private final NonMagnifiableWindowContainers mImeWindowsContainers = - new NonMagnifiableWindowContainers("mImeWindowsContainers", mWmService); + private final NonAppWindowContainers mImeWindowsContainers = + new NonAppWindowContainers("mImeWindowsContainers", mWmService); private WindowState mTmpWindow; private WindowState mTmpWindow2; @@ -4642,16 +4642,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } } - private class NonMagnifiableWindowContainers extends NonAppWindowContainers { - NonMagnifiableWindowContainers(String name, WindowManagerService service) { - super(name, service); - } - - @Override - void applyMagnificationSpec(Transaction t, MagnificationSpec spec) { - } - }; - SurfaceControl.Builder makeSurface(SurfaceSession s) { return mWmService.makeSurfaceBuilder(s) .setParent(mWindowingLayer); diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index 432d75e9a4e3..363db5439f27 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -294,7 +294,16 @@ class KeyguardController { /** * Called when occluded state changed. */ - private void handleOccludedChanged() { + private void handleOccludedChanged(int displayId) { + // TODO(b/113840485): Handle app transition for individual display, and apply occluded + // state change to secondary displays. + // For now, only default display fully supports occluded change. Other displays only + // updates keygaurd sleep token on that display. + if (displayId != DEFAULT_DISPLAY) { + updateKeyguardSleepToken(displayId); + return; + } + mWindowManager.onKeyguardOccludedChanged(isDisplayOccluded(DEFAULT_DISPLAY)); if (isKeyguardLocked()) { mWindowManager.deferSurfaceLayout(); @@ -303,7 +312,7 @@ class KeyguardController { .prepareAppTransition(resolveOccludeTransit(), false /* alwaysKeepCurrent */, 0 /* flags */, true /* forceOverride */); - updateKeyguardSleepToken(); + updateKeyguardSleepToken(DEFAULT_DISPLAY); mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); mWindowManager.executeAppTransition(); } finally { @@ -395,13 +404,16 @@ class KeyguardController { for (int displayNdx = mRootActivityContainer.getChildCount() - 1; displayNdx >= 0; displayNdx--) { final ActivityDisplay display = mRootActivityContainer.getChildAt(displayNdx); - final int displayId = display.mDisplayId; - final KeyguardDisplayState state = getDisplay(displayId); - if (isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken == null) { - state.acquiredSleepToken(); - } else if (!isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken != null) { - state.releaseSleepToken(); - } + updateKeyguardSleepToken(display.mDisplayId); + } + } + + private void updateKeyguardSleepToken(int displayId) { + final KeyguardDisplayState state = getDisplay(displayId); + if (isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken == null) { + state.acquiredSleepToken(); + } else if (!isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken != null) { + state.releaseSleepToken(); } } @@ -483,11 +495,8 @@ class KeyguardController { mOccluded |= controller.mWindowManager.isShowingDream(); } - // TODO(b/113840485): Handle app transition for individual display, and apply occluded - // state change to secondary displays. - // For now, only default display can change occluded. - if (lastOccluded != mOccluded && mDisplayId == DEFAULT_DISPLAY) { - controller.handleOccludedChanged(); + if (lastOccluded != mOccluded) { + controller.handleOccludedChanged(mDisplayId); } if (lastDismissActivity != mDismissingKeyguardActivity && !mOccluded && mDismissingKeyguardActivity != null diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java index 3c9a46b43a2f..0b63f484c8e2 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java @@ -26,7 +26,6 @@ import android.app.ActivityManager; import android.app.ActivityManager.TaskSnapshot; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; -import android.hardware.HardwareBuffer; import android.os.Process; import android.os.SystemClock; import android.util.ArraySet; @@ -363,8 +362,7 @@ class TaskSnapshotPersister { // TODO(b/116112787) TaskSnapshot needs bookkeep the ColorSpace of the // hardware bitmap when created. final Bitmap bitmap = Bitmap.wrapHardwareBuffer( - HardwareBuffer.createFromGraphicBuffer(mSnapshot.getSnapshot()), - mSnapshot.getColorSpace()); + mSnapshot.getSnapshot(), mSnapshot.getColorSpace()); if (bitmap == null) { Slog.e(TAG, "Invalid task snapshot hw bitmap"); return false; diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index 166a33d7a560..da873b8bc308 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -35,7 +35,6 @@ import static com.android.server.wm.WindowManagerService.H.WALLPAPER_DRAW_PENDIN import android.graphics.Bitmap; import android.graphics.Rect; -import android.hardware.HardwareBuffer; import android.os.Bundle; import android.os.Debug; import android.os.IBinder; @@ -744,8 +743,7 @@ class WallpaperController { return null; } return Bitmap.wrapHardwareBuffer( - HardwareBuffer.createFromGraphicBuffer(wallpaperBuffer.getGraphicBuffer()), - wallpaperBuffer.getColorSpace()); + wallpaperBuffer.getGraphicBuffer(), wallpaperBuffer.getColorSpace()); } private WindowState getTopVisibleWallpaper() { |