Merge "Update wifi header summary text to show metered state" into pi-dev
diff --git a/Android.bp b/Android.bp
index 4d5d998..ce93568 100644
--- a/Android.bp
+++ b/Android.bp
@@ -145,11 +145,11 @@
":libcamera_client_framework_aidl",
"core/java/android/hardware/IConsumerIrService.aidl",
"core/java/android/hardware/ISerialManager.aidl",
+ "core/java/android/hardware/biometrics/IBiometricDialogReceiver.aidl",
"core/java/android/hardware/display/IDisplayManager.aidl",
"core/java/android/hardware/display/IDisplayManagerCallback.aidl",
"core/java/android/hardware/display/IVirtualDisplayCallback.aidl",
"core/java/android/hardware/fingerprint/IFingerprintClientActiveCallback.aidl",
- "core/java/android/hardware/fingerprint/IFingerprintDialogReceiver.aidl",
"core/java/android/hardware/fingerprint/IFingerprintService.aidl",
"core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl",
"core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl",
diff --git a/Android.mk b/Android.mk
index b630c3f..e219661 100644
--- a/Android.mk
+++ b/Android.mk
@@ -861,14 +861,11 @@
# ==== hiddenapi lists =======================================
-# Copy blacklist and light greylist over into the build folder.
+# Copy light and dark greylist over into the build folder.
# This is for ART buildbots which need to mock these lists and have alternative
# rules for building them. Other rules in the build system should depend on the
# files in the build folder.
-$(eval $(call copy-one-file,frameworks/base/config/hiddenapi-blacklist.txt,\
- $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)))
-
# Automatically add all methods which match the following signatures.
# These need to be greylisted in order to allow applications to write their
# own serializers.
@@ -891,25 +888,31 @@
<(grep -E "\->("$(subst $(space),"|",$(REGEX_SERIALIZATION))")$$" $(PRIVATE_API)) \
> $@
+$(eval $(call copy-one-file,frameworks/base/config/hiddenapi-dark-greylist.txt,\
+ $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST)))
+
# Generate dark greylist as private API minus (blacklist plus light greylist).
-$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
-$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): BLACKLIST := $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)
-$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): LIGHT_GREYLIST := $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST)
-$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) \
- $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST) \
- $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST)
- if [ ! -z "`comm -12 <(sort $(BLACKLIST)) <(sort $(LIGHT_GREYLIST))`" ]; then \
- echo "There should be no overlap between $(BLACKLIST) and $(LIGHT_GREYLIST)" 1>&2; \
+$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST): PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
+$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST): LIGHT_GREYLIST := $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST)
+$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST): DARK_GREYLIST := $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST)
+$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST): $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) \
+ $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) \
+ $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST)
+ if [ ! -z "`comm -12 <(sort $(LIGHT_GREYLIST)) <(sort $(DARK_GREYLIST))`" ]; then \
+ echo "There should be no overlap between $(LIGHT_GREYLIST) and $(DARK_GREYLIST)" 1>&2; \
+ comm -12 <(sort $(LIGHT_GREYLIST)) <(sort $(DARK_GREYLIST)) 1>&2; \
exit 1; \
- elif [ ! -z "`comm -13 <(sort $(PRIVATE_API)) <(sort $(BLACKLIST))`" ]; then \
- echo "$(BLACKLIST) must be a subset of $(PRIVATE_API)" 1>&2; \
- exit 2; \
elif [ ! -z "`comm -13 <(sort $(PRIVATE_API)) <(sort $(LIGHT_GREYLIST))`" ]; then \
echo "$(LIGHT_GREYLIST) must be a subset of $(PRIVATE_API)" 1>&2; \
+ comm -13 <(sort $(PRIVATE_API)) <(sort $(LIGHT_GREYLIST)) 1>&2; \
+ exit 2; \
+ elif [ ! -z "`comm -13 <(sort $(PRIVATE_API)) <(sort $(DARK_GREYLIST))`" ]; then \
+ echo "$(DARK_GREYLIST) must be a subset of $(PRIVATE_API)" 1>&2; \
+ comm -13 <(sort $(PRIVATE_API)) <(sort $(DARK_GREYLIST)) 1>&2; \
exit 3; \
fi
- comm -23 <(sort $(PRIVATE_API)) <(sort $(BLACKLIST) $(LIGHT_GREYLIST)) > $@
+ comm -23 <(sort $(PRIVATE_API)) <(sort $(LIGHT_GREYLIST) $(DARK_GREYLIST)) > $@
# Include subdirectory makefiles
# ============================================================
diff --git a/api/current.txt b/api/current.txt
index 64b2d58..d5ce5d4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -142,7 +142,8 @@
field public static final java.lang.String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
field public static final java.lang.String UNINSTALL_SHORTCUT = "com.android.launcher.permission.UNINSTALL_SHORTCUT";
field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
- field public static final java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
+ field public static final java.lang.String USE_BIOMETRIC = "android.permission.USE_BIOMETRIC";
+ field public static final deprecated java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
field public static final java.lang.String VIBRATE = "android.permission.VIBRATE";
field public static final java.lang.String WAKE_LOCK = "android.permission.WAKE_LOCK";
@@ -5877,6 +5878,8 @@
method public java.lang.CharSequence getTitle();
method public boolean isEnabled();
method public void setEnabled(boolean);
+ method public void setShouldShowIcon(boolean);
+ method public boolean shouldShowIcon();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.RemoteAction> CREATOR;
}
@@ -6261,6 +6264,7 @@
method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler);
method public void clear() throws java.io.IOException;
method public void clear(int) throws java.io.IOException;
+ method public void clearWallpaper();
method public void clearWallpaperOffsets(android.os.IBinder);
method public void forgetLoadedWallpaper();
method public android.graphics.drawable.Drawable getBuiltInDrawable();
@@ -6287,6 +6291,7 @@
method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException;
method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean, int) throws java.io.IOException;
+ method public void setDisplayPadding(android.graphics.Rect);
method public void setResource(int) throws java.io.IOException;
method public int setResource(int, int) throws java.io.IOException;
method public void setStream(java.io.InputStream) throws java.io.IOException;
@@ -6680,9 +6685,12 @@
field public static final int ID_TYPE_IMEI = 4; // 0x4
field public static final int ID_TYPE_MEID = 8; // 0x8
field public static final int ID_TYPE_SERIAL = 2; // 0x2
+ field public static final int KEYGUARD_DISABLE_BIOMETRICS = 416; // 0x1a0
+ field public static final int KEYGUARD_DISABLE_FACE = 128; // 0x80
field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
field public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0; // 0x0
field public static final int KEYGUARD_DISABLE_FINGERPRINT = 32; // 0x20
+ field public static final int KEYGUARD_DISABLE_IRIS = 256; // 0x100
field public static final int KEYGUARD_DISABLE_REMOTE_INPUT = 64; // 0x40
field public static final int KEYGUARD_DISABLE_SECURE_CAMERA = 2; // 0x2
field public static final int KEYGUARD_DISABLE_SECURE_NOTIFICATIONS = 4; // 0x4
@@ -7332,6 +7340,20 @@
field public static final android.os.Parcelable.Creator<android.app.usage.ConfigurationStats> CREATOR;
}
+ public final class EventStats implements android.os.Parcelable {
+ ctor public EventStats(android.app.usage.EventStats);
+ method public void add(android.app.usage.EventStats);
+ method public int describeContents();
+ method public int getCount();
+ method public int getEventType();
+ method public long getFirstTimeStamp();
+ method public long getLastTimeStamp();
+ method public long getLastTimeUsed();
+ method public long getTotalTime();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.usage.EventStats> CREATOR;
+ }
+
public final class ExternalStorageStats implements android.os.Parcelable {
method public int describeContents();
method public long getAppBytes();
@@ -7437,6 +7459,8 @@
field public static final int MOVE_TO_BACKGROUND = 2; // 0x2
field public static final int MOVE_TO_FOREGROUND = 1; // 0x1
field public static final int NONE = 0; // 0x0
+ field public static final int SCREEN_INTERACTIVE = 15; // 0xf
+ field public static final int SCREEN_NON_INTERACTIVE = 16; // 0x10
field public static final int SHORTCUT_INVOCATION = 8; // 0x8
field public static final int STANDBY_BUCKET_CHANGED = 11; // 0xb
field public static final int USER_INTERACTION = 7; // 0x7
@@ -7460,6 +7484,7 @@
method public boolean isAppInactive(java.lang.String);
method public java.util.Map<java.lang.String, android.app.usage.UsageStats> queryAndAggregateUsageStats(long, long);
method public java.util.List<android.app.usage.ConfigurationStats> queryConfigurations(int, long, long);
+ method public java.util.List<android.app.usage.EventStats> queryEventStats(int, long, long);
method public android.app.usage.UsageEvents queryEvents(long, long);
method public android.app.usage.UsageEvents queryEventsForSelf(long, long);
method public java.util.List<android.app.usage.UsageStats> queryUsageStats(int, long, long);
@@ -9886,6 +9911,8 @@
field public static final java.lang.String ACTION_MEDIA_UNMOUNTABLE = "android.intent.action.MEDIA_UNMOUNTABLE";
field public static final java.lang.String ACTION_MEDIA_UNMOUNTED = "android.intent.action.MEDIA_UNMOUNTED";
field public static final java.lang.String ACTION_MY_PACKAGE_REPLACED = "android.intent.action.MY_PACKAGE_REPLACED";
+ field public static final java.lang.String ACTION_MY_PACKAGE_SUSPENDED = "android.intent.action.MY_PACKAGE_SUSPENDED";
+ field public static final java.lang.String ACTION_MY_PACKAGE_UNSUSPENDED = "android.intent.action.MY_PACKAGE_UNSUSPENDED";
field public static final java.lang.String ACTION_NEW_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL";
field public static final java.lang.String ACTION_OPEN_DOCUMENT = "android.intent.action.OPEN_DOCUMENT";
field public static final java.lang.String ACTION_OPEN_DOCUMENT_TREE = "android.intent.action.OPEN_DOCUMENT_TREE";
@@ -10046,6 +10073,7 @@
field public static final java.lang.String EXTRA_SPLIT_NAME = "android.intent.extra.SPLIT_NAME";
field public static final java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
field public static final java.lang.String EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
+ field public static final java.lang.String EXTRA_SUSPENDED_PACKAGE_EXTRAS = "android.intent.extra.SUSPENDED_PACKAGE_EXTRAS";
field public static final java.lang.String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE";
field public static final java.lang.String EXTRA_TEXT = "android.intent.extra.TEXT";
field public static final java.lang.String EXTRA_TITLE = "android.intent.extra.TITLE";
@@ -11159,7 +11187,7 @@
method public abstract android.content.res.Resources getResourcesForApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int);
- method public android.os.PersistableBundle getSuspendedPackageAppExtras();
+ method public android.os.Bundle getSuspendedPackageAppExtras();
method public abstract android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
method public abstract java.lang.String[] getSystemSharedLibraryNames();
method public abstract java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
@@ -13306,14 +13334,9 @@
method public void rotate(float);
method public final void rotate(float, float, float);
method public int save();
- method public deprecated int save(int);
- method public deprecated int saveLayer(android.graphics.RectF, android.graphics.Paint, int);
method public int saveLayer(android.graphics.RectF, android.graphics.Paint);
- method public deprecated int saveLayer(float, float, float, float, android.graphics.Paint, int);
method public int saveLayer(float, float, float, float, android.graphics.Paint);
- method public deprecated int saveLayerAlpha(android.graphics.RectF, int, int);
method public int saveLayerAlpha(android.graphics.RectF, int);
- method public deprecated int saveLayerAlpha(float, float, float, float, int, int);
method public int saveLayerAlpha(float, float, float, float, int);
method public void scale(float, float);
method public final void scale(float, float, float, float);
@@ -13323,12 +13346,6 @@
method public void setMatrix(android.graphics.Matrix);
method public void skew(float, float);
method public void translate(float, float);
- field public static final int ALL_SAVE_FLAG = 31; // 0x1f
- field public static final deprecated int CLIP_SAVE_FLAG = 2; // 0x2
- field public static final deprecated int CLIP_TO_LAYER_SAVE_FLAG = 16; // 0x10
- field public static final deprecated int FULL_COLOR_LAYER_SAVE_FLAG = 8; // 0x8
- field public static final deprecated int HAS_ALPHA_LAYER_SAVE_FLAG = 4; // 0x4
- field public static final deprecated int MATRIX_SAVE_FLAG = 1; // 0x1
}
public static final class Canvas.EdgeType extends java.lang.Enum {
@@ -15712,6 +15729,62 @@
}
+package android.hardware.biometrics {
+
+ public class BiometricDialog {
+ method public void authenticate(android.hardware.biometrics.BiometricDialog.CryptoObject, android.os.CancellationSignal, java.util.concurrent.Executor, android.hardware.biometrics.BiometricDialog.AuthenticationCallback);
+ method public void authenticate(android.os.CancellationSignal, java.util.concurrent.Executor, android.hardware.biometrics.BiometricDialog.AuthenticationCallback);
+ field public static final int BIOMETRIC_ACQUIRED_GOOD = 0; // 0x0
+ field public static final int BIOMETRIC_ACQUIRED_IMAGER_DIRTY = 3; // 0x3
+ field public static final int BIOMETRIC_ACQUIRED_INSUFFICIENT = 2; // 0x2
+ field public static final int BIOMETRIC_ACQUIRED_PARTIAL = 1; // 0x1
+ field public static final int BIOMETRIC_ACQUIRED_TOO_FAST = 5; // 0x5
+ field public static final int BIOMETRIC_ACQUIRED_TOO_SLOW = 4; // 0x4
+ field public static final int BIOMETRIC_ERROR_CANCELED = 5; // 0x5
+ field public static final int BIOMETRIC_ERROR_HW_NOT_PRESENT = 12; // 0xc
+ field public static final int BIOMETRIC_ERROR_HW_UNAVAILABLE = 1; // 0x1
+ field public static final int BIOMETRIC_ERROR_LOCKOUT = 7; // 0x7
+ field public static final int BIOMETRIC_ERROR_LOCKOUT_PERMANENT = 9; // 0x9
+ field public static final int BIOMETRIC_ERROR_NO_BIOMETRICS = 11; // 0xb
+ field public static final int BIOMETRIC_ERROR_NO_SPACE = 4; // 0x4
+ field public static final int BIOMETRIC_ERROR_TIMEOUT = 3; // 0x3
+ field public static final int BIOMETRIC_ERROR_UNABLE_TO_PROCESS = 2; // 0x2
+ field public static final int BIOMETRIC_ERROR_USER_CANCELED = 10; // 0xa
+ field public static final int BIOMETRIC_ERROR_VENDOR = 8; // 0x8
+ }
+
+ public static abstract class BiometricDialog.AuthenticationCallback {
+ ctor public BiometricDialog.AuthenticationCallback();
+ method public void onAuthenticationError(int, java.lang.CharSequence);
+ method public void onAuthenticationFailed();
+ method public void onAuthenticationHelp(int, java.lang.CharSequence);
+ method public void onAuthenticationSucceeded(android.hardware.biometrics.BiometricDialog.AuthenticationResult);
+ }
+
+ public static class BiometricDialog.AuthenticationResult {
+ method public android.hardware.biometrics.BiometricDialog.CryptoObject getCryptoObject();
+ }
+
+ public static class BiometricDialog.Builder {
+ ctor public BiometricDialog.Builder(android.content.Context);
+ method public android.hardware.biometrics.BiometricDialog build();
+ method public android.hardware.biometrics.BiometricDialog.Builder setDescription(java.lang.CharSequence);
+ method public android.hardware.biometrics.BiometricDialog.Builder setNegativeButton(java.lang.CharSequence, java.util.concurrent.Executor, android.content.DialogInterface.OnClickListener);
+ method public android.hardware.biometrics.BiometricDialog.Builder setSubtitle(java.lang.CharSequence);
+ method public android.hardware.biometrics.BiometricDialog.Builder setTitle(java.lang.CharSequence);
+ }
+
+ public static final class BiometricDialog.CryptoObject {
+ ctor public BiometricDialog.CryptoObject(java.security.Signature);
+ ctor public BiometricDialog.CryptoObject(javax.crypto.Cipher);
+ ctor public BiometricDialog.CryptoObject(javax.crypto.Mac);
+ method public javax.crypto.Cipher getCipher();
+ method public javax.crypto.Mac getMac();
+ method public java.security.Signature getSignature();
+ }
+
+}
+
package android.hardware.camera2 {
public class CameraAccessException extends android.util.AndroidException {
@@ -15797,6 +15870,7 @@
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AWB;
field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Integer>> CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> DEPTH_DEPTH_IS_EXCLUSIVE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> DISTORTION_CORRECTION_AVAILABLE_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> EDGE_AVAILABLE_EDGE_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> FLASH_INFO_AVAILABLE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES;
@@ -16033,6 +16107,9 @@
field public static final int CONTROL_SCENE_MODE_THEATRE = 7; // 0x7
field public static final int CONTROL_VIDEO_STABILIZATION_MODE_OFF = 0; // 0x0
field public static final int CONTROL_VIDEO_STABILIZATION_MODE_ON = 1; // 0x1
+ field public static final int DISTORTION_CORRECTION_MODE_FAST = 1; // 0x1
+ field public static final int DISTORTION_CORRECTION_MODE_HIGH_QUALITY = 2; // 0x2
+ field public static final int DISTORTION_CORRECTION_MODE_OFF = 0; // 0x0
field public static final int EDGE_MODE_FAST = 1; // 0x1
field public static final int EDGE_MODE_HIGH_QUALITY = 2; // 0x2
field public static final int EDGE_MODE_OFF = 0; // 0x0
@@ -16185,6 +16262,7 @@
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_SCENE_MODE;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_VIDEO_STABILIZATION_MODE;
field public static final android.os.Parcelable.Creator<android.hardware.camera2.CaptureRequest> CREATOR;
+ field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> DISTORTION_CORRECTION_MODE;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> EDGE_MODE;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> FLASH_MODE;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> HOT_PIXEL_MODE;
@@ -16267,6 +16345,7 @@
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_POST_RAW_SENSITIVITY_BOOST;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_SCENE_MODE;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_VIDEO_STABILIZATION_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> DISTORTION_CORRECTION_MODE;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> EDGE_MODE;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> FLASH_MODE;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> FLASH_STATE;
@@ -16541,58 +16620,6 @@
package android.hardware.fingerprint {
- public class FingerprintDialog {
- method public void authenticate(android.hardware.fingerprint.FingerprintDialog.CryptoObject, android.os.CancellationSignal, java.util.concurrent.Executor, android.hardware.fingerprint.FingerprintDialog.AuthenticationCallback);
- method public void authenticate(android.os.CancellationSignal, java.util.concurrent.Executor, android.hardware.fingerprint.FingerprintDialog.AuthenticationCallback);
- field public static final int FINGERPRINT_ACQUIRED_GOOD = 0; // 0x0
- field public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3; // 0x3
- field public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2; // 0x2
- field public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; // 0x1
- field public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; // 0x5
- field public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; // 0x4
- field public static final int FINGERPRINT_ERROR_CANCELED = 5; // 0x5
- field public static final int FINGERPRINT_ERROR_HW_NOT_PRESENT = 12; // 0xc
- field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1
- field public static final int FINGERPRINT_ERROR_LOCKOUT = 7; // 0x7
- field public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9; // 0x9
- field public static final int FINGERPRINT_ERROR_NO_FINGERPRINTS = 11; // 0xb
- field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4
- field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3
- field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2
- field public static final int FINGERPRINT_ERROR_USER_CANCELED = 10; // 0xa
- field public static final int FINGERPRINT_ERROR_VENDOR = 8; // 0x8
- }
-
- public static abstract class FingerprintDialog.AuthenticationCallback {
- ctor public FingerprintDialog.AuthenticationCallback();
- method public void onAuthenticationError(int, java.lang.CharSequence);
- method public void onAuthenticationFailed();
- method public void onAuthenticationHelp(int, java.lang.CharSequence);
- method public void onAuthenticationSucceeded(android.hardware.fingerprint.FingerprintDialog.AuthenticationResult);
- }
-
- public static class FingerprintDialog.AuthenticationResult {
- method public android.hardware.fingerprint.FingerprintDialog.CryptoObject getCryptoObject();
- }
-
- public static class FingerprintDialog.Builder {
- ctor public FingerprintDialog.Builder();
- method public android.hardware.fingerprint.FingerprintDialog build(android.content.Context);
- method public android.hardware.fingerprint.FingerprintDialog.Builder setDescription(java.lang.CharSequence);
- method public android.hardware.fingerprint.FingerprintDialog.Builder setNegativeButton(java.lang.CharSequence, java.util.concurrent.Executor, android.content.DialogInterface.OnClickListener);
- method public android.hardware.fingerprint.FingerprintDialog.Builder setSubtitle(java.lang.CharSequence);
- method public android.hardware.fingerprint.FingerprintDialog.Builder setTitle(java.lang.CharSequence);
- }
-
- public static final class FingerprintDialog.CryptoObject {
- ctor public FingerprintDialog.CryptoObject(java.security.Signature);
- ctor public FingerprintDialog.CryptoObject(javax.crypto.Cipher);
- ctor public FingerprintDialog.CryptoObject(javax.crypto.Mac);
- method public javax.crypto.Cipher getCipher();
- method public javax.crypto.Mac getMac();
- method public java.security.Signature getSignature();
- }
-
public deprecated class FingerprintManager {
method public deprecated void authenticate(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.CancellationSignal, int, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, android.os.Handler);
method public deprecated boolean hasEnrolledFingerprints();
@@ -32041,7 +32068,6 @@
field public static final java.lang.String BASE_OS;
field public static final java.lang.String CODENAME;
field public static final java.lang.String INCREMENTAL;
- field public static final int MIN_SUPPORTED_TARGET_SDK_INT;
field public static final int PREVIEW_SDK_INT;
field public static final java.lang.String RELEASE;
field public static final deprecated java.lang.String SDK;
@@ -38328,10 +38354,8 @@
method public void shutdown();
}
- public static abstract class SEService.SecureElementListener extends android.os.Binder {
- ctor public SEService.SecureElementListener();
- method public android.os.IBinder asBinder();
- method public void serviceConnected();
+ public static abstract interface SEService.SecureElementListener {
+ method public abstract void onServiceConnected();
}
public class Session {
@@ -38341,9 +38365,7 @@
method public android.se.omapi.Reader getReader();
method public boolean isClosed();
method public android.se.omapi.Channel openBasicChannel(byte[], byte) throws java.io.IOException;
- method public android.se.omapi.Channel openBasicChannel(byte[]) throws java.io.IOException;
method public android.se.omapi.Channel openLogicalChannel(byte[], byte) throws java.io.IOException;
- method public android.se.omapi.Channel openLogicalChannel(byte[]) throws java.io.IOException;
}
}
@@ -38611,6 +38633,7 @@
method public boolean isDigestsSpecified();
method public boolean isInvalidatedByBiometricEnrollment();
method public boolean isRandomizedEncryptionRequired();
+ method public boolean isTrustedUserPresenceRequired();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationValidWhileOnBody();
method public boolean isUserConfirmationRequired();
@@ -38629,6 +38652,7 @@
method public android.security.keystore.KeyProtection.Builder setKeyValidityStart(java.util.Date);
method public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
method public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
+ method public android.security.keystore.KeyProtection.Builder setTrustedUserPresenceRequired(boolean);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationRequired(boolean);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int);
@@ -41566,7 +41590,6 @@
field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool";
field public static final java.lang.String KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL = "editable_voicemail_number_bool";
field public static final java.lang.String KEY_EDITABLE_VOICEMAIL_NUMBER_SETTING_BOOL = "editable_voicemail_number_setting_bool";
- field public static final java.lang.String KEY_ENABLE_APPS_STRING_ARRAY = "enable_apps_string_array";
field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool";
field public static final java.lang.String KEY_FORCE_HOME_NETWORK_BOOL = "force_home_network_bool";
field public static final java.lang.String KEY_GSM_DTMF_TONE_DELAY_INT = "gsm_dtmf_tone_delay_int";
@@ -42367,12 +42390,11 @@
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
method public boolean isConcurrentVoiceAndDataSupported();
- method public deprecated boolean isDataEnabled();
+ method public boolean isDataEnabled();
method public boolean isHearingAidCompatibilitySupported();
method public boolean isNetworkRoaming();
method public boolean isSmsCapable();
method public deprecated boolean isTtyModeSupported();
- method public boolean isUserMobileDataEnabled();
method public boolean isVoiceCapable();
method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
method public boolean isWorldPhone();
@@ -42383,13 +42405,12 @@
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
method public void sendVisualVoicemailSms(java.lang.String, int, java.lang.String, android.app.PendingIntent);
- method public deprecated void setDataEnabled(boolean);
+ method public void setDataEnabled(boolean);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public void setNetworkSelectionModeAutomatic();
method public boolean setNetworkSelectionModeManual(java.lang.String, boolean);
method public boolean setOperatorBrandOverride(java.lang.String);
method public boolean setPreferredNetworkTypeToGlobal();
- method public void setUserMobileDataEnabled(boolean);
method public void setVisualVoicemailSmsFilterSettings(android.telephony.VisualVoicemailSmsFilterSettings);
method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
method public deprecated void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
@@ -42664,6 +42685,7 @@
field public static final int EMBEDDED_SUBSCRIPTION_RESULT_OK = 0; // 0x0
field public static final int EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR = 1; // 0x1
field public static final java.lang.String EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE";
+ field public static final java.lang.String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION";
field public static final java.lang.String META_DATA_CARRIER_ICON = "android.telephony.euicc.carriericon";
}
@@ -50342,17 +50364,14 @@
public final class TextClassification implements android.os.Parcelable {
method public int describeContents();
+ method public java.util.List<android.app.RemoteAction> getActions();
method public float getConfidenceScore(java.lang.String);
method public java.lang.String getEntity(int);
method public int getEntityCount();
- method public android.graphics.drawable.Drawable getIcon();
- method public android.content.Intent getIntent();
- method public java.lang.CharSequence getLabel();
- method public android.view.View.OnClickListener getOnClickListener();
- method public int getSecondaryActionsCount();
- method public android.graphics.drawable.Drawable getSecondaryIcon(int);
- method public android.content.Intent getSecondaryIntent(int);
- method public java.lang.CharSequence getSecondaryLabel(int);
+ method public deprecated android.graphics.drawable.Drawable getIcon();
+ method public deprecated android.content.Intent getIntent();
+ method public deprecated java.lang.CharSequence getLabel();
+ method public deprecated android.view.View.OnClickListener getOnClickListener();
method public java.lang.String getSignature();
method public java.lang.String getText();
method public void writeToParcel(android.os.Parcel, int);
@@ -50361,15 +50380,13 @@
public static final class TextClassification.Builder {
ctor public TextClassification.Builder();
- method public android.view.textclassifier.TextClassification.Builder addSecondaryAction(android.content.Intent, java.lang.String, android.graphics.drawable.Drawable);
+ method public android.view.textclassifier.TextClassification.Builder addAction(android.app.RemoteAction);
method public android.view.textclassifier.TextClassification build();
- method public android.view.textclassifier.TextClassification.Builder clearSecondaryActions();
method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float);
- method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable);
- method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent);
- method public android.view.textclassifier.TextClassification.Builder setLabel(java.lang.String);
- method public android.view.textclassifier.TextClassification.Builder setOnClickListener(android.view.View.OnClickListener);
- method public android.view.textclassifier.TextClassification.Builder setPrimaryAction(android.content.Intent, java.lang.String, android.graphics.drawable.Drawable);
+ method public deprecated android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable);
+ method public deprecated android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent);
+ method public deprecated android.view.textclassifier.TextClassification.Builder setLabel(java.lang.String);
+ method public deprecated android.view.textclassifier.TextClassification.Builder setOnClickListener(android.view.View.OnClickListener);
method public android.view.textclassifier.TextClassification.Builder setSignature(java.lang.String);
method public android.view.textclassifier.TextClassification.Builder setText(java.lang.String);
}
diff --git a/api/removed.txt b/api/removed.txt
index 4279c31..9fe25c9 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -168,6 +168,17 @@
public class Canvas {
method public deprecated boolean clipRegion(android.graphics.Region, android.graphics.Region.Op);
method public deprecated boolean clipRegion(android.graphics.Region);
+ method public deprecated int save(int);
+ method public deprecated int saveLayer(android.graphics.RectF, android.graphics.Paint, int);
+ method public deprecated int saveLayer(float, float, float, float, android.graphics.Paint, int);
+ method public deprecated int saveLayerAlpha(android.graphics.RectF, int, int);
+ method public deprecated int saveLayerAlpha(float, float, float, float, int, int);
+ field public static final int ALL_SAVE_FLAG = 31; // 0x1f
+ field public static final deprecated int CLIP_SAVE_FLAG = 2; // 0x2
+ field public static final deprecated int CLIP_TO_LAYER_SAVE_FLAG = 16; // 0x10
+ field public static final deprecated int FULL_COLOR_LAYER_SAVE_FLAG = 8; // 0x8
+ field public static final deprecated int HAS_ALPHA_LAYER_SAVE_FLAG = 4; // 0x4
+ field public static final deprecated int MATRIX_SAVE_FLAG = 1; // 0x1
}
public final class ImageDecoder implements java.lang.AutoCloseable {
diff --git a/api/system-current.txt b/api/system-current.txt
index e049f53..5568dba 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -400,10 +400,8 @@
}
public class WallpaperManager {
- method public void clearWallpaper();
method public void clearWallpaper(int, int);
method public void setDisplayOffset(android.os.IBinder, int, int);
- method public void setDisplayPadding(android.graphics.Rect);
method public boolean setWallpaperComponent(android.content.ComponentName);
}
@@ -5503,7 +5501,6 @@
field public static final int EUICC_OTA_NOT_NEEDED = 4; // 0x4
field public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5; // 0x5
field public static final int EUICC_OTA_SUCCEEDED = 3; // 0x3
- field public static final java.lang.String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION";
field public static final java.lang.String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS";
}
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index a35570b..a458c07 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -199,11 +199,6 @@
sp<MetricsManager> newMetricsManager =
new MetricsManager(key, config, mTimeBaseSec, mUidMap,
mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
- auto it = mMetricsManagers.find(key);
- if (it == mMetricsManagers.end() && mMetricsManagers.size() > StatsdStats::kMaxConfigCount) {
- ALOGE("Can't accept more configs!");
- return;
- }
if (newMetricsManager->isConfigValid()) {
mUidMap->OnConfigUpdated(key);
@@ -213,7 +208,6 @@
mUidMap->addListener(newMetricsManager.get());
}
mMetricsManagers[key] = newMetricsManager;
- // Why doesn't this work? mMetricsManagers.insert({key, std::move(newMetricsManager)});
VLOG("StatsdConfig valid");
} else {
// If there is any error in the config, don't use it.
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 99611f4..2095649 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -111,13 +111,14 @@
BluetoothEnabledStateChanged bluetooth_enabled_state_changed = 67;
BluetoothConnectionStateChanged bluetooth_connection_state_changed = 68;
BluetoothA2dpAudioStateChanged bluetooth_a2dp_audio_state_changed = 69;
- UsbConnectorStateChanged usb_connector_changed = 70;
+ UsbConnectorStateChanged usb_connector_state_changed = 70;
SpeakerImpedanceReported speaker_impedance_reported = 71;
HardwareFailed hardware_failed = 72;
PhysicalDropDetected physical_drop_detected = 73;
ChargeCyclesReported charge_cycles_reported = 74;
MobileConnectionStateChanged mobile_connection_state_changed = 75;
MobileRadioTechnologyChanged mobile_radio_technology_changed = 76;
+ UsbDeviceAttached usb_device_attached = 77;
}
// Pulled events will start at field 10000.
@@ -291,7 +292,7 @@
* Logs when a sensor state changes.
*
* Logged from:
- * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ * frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
*/
message SensorStateChanged {
repeated AttributionNode attribution_node = 1;
@@ -329,7 +330,7 @@
* Logs when a sync manager sync state changes.
*
* Logged from:
- * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ * frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
*/
message SyncStateChanged {
repeated AttributionNode attribution_node = 1;
@@ -348,7 +349,7 @@
* Logs when a job scheduler job state changes.
*
* Logged from:
- * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ * frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
*/
message ScheduledJobStateChanged {
repeated AttributionNode attribution_node = 1;
@@ -365,7 +366,7 @@
// The reason a job has stopped.
// This is only applicable when the state is FINISHED.
- // The default value is CANCELED.
+ // The default value is STOP_REASON_UNKNOWN.
optional android.app.job.StopReasonEnum stop_reason = 4;
}
@@ -373,7 +374,7 @@
* Logs when the audio state changes.
*
* Logged from:
- * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ * frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
*/
message AudioStateChanged {
repeated AttributionNode attribution_node = 1;
@@ -381,6 +382,8 @@
enum State {
OFF = 0;
ON = 1;
+ // RESET indicates all audio stopped. Used when it (re)starts (e.g. after it crashes).
+ RESET = 2;
}
optional State state = 2;
}
@@ -389,7 +392,7 @@
* Logs when the video codec state changes.
*
* Logged from:
- * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ * frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
*/
message MediaCodecActivityChanged {
repeated AttributionNode attribution_node = 1;
@@ -397,6 +400,8 @@
enum State {
OFF = 0;
ON = 1;
+ // RESET indicates all mediaCodec stopped. Used when it (re)starts (e.g. after it crashes).
+ RESET = 2;
}
optional State state = 2;
}
@@ -405,7 +410,7 @@
* Logs when the flashlight state changes.
*
* Logged from:
- * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ * frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
*/
message FlashlightStateChanged {
repeated AttributionNode attribution_node = 1;
@@ -413,6 +418,8 @@
enum State {
OFF = 0;
ON = 1;
+ // RESET indicates all flashlight stopped. Used when it (re)starts (e.g. after it crashes).
+ RESET = 2;
}
optional State state = 2;
}
@@ -421,7 +428,7 @@
* Logs when the camera state changes.
*
* Logged from:
- * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ * frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
*/
message CameraStateChanged {
repeated AttributionNode attribution_node = 1;
@@ -429,6 +436,8 @@
enum State {
OFF = 0;
ON = 1;
+ // RESET indicates all camera stopped. Used when it (re)starts (e.g. after it crashes).
+ RESET = 2;
}
optional State state = 2;
}
@@ -966,6 +975,21 @@
optional int32 sim_slot_index = 2;
}
+/**
+ * Logs the VID and PID of any connected USB devices.
+ *
+ * Notes if any Audio, HID (input buttons/mouse/keyboard), or Storage interfaces are present.
+ *
+ * Logged by Vendor.
+ */
+message UsbDeviceAttached {
+ optional int32 vid = 1;
+ optional int32 pid = 2;
+ optional bool has_audio = 3;
+ optional bool has_hid = 4;
+ optional bool has_storage = 5;
+}
+
/**
* Logs when Bluetooth is enabled and disabled.
@@ -1103,6 +1127,8 @@
optional int32 confidence_pctg = 1;
// Peak acceleration of the drop, in 1/1000s of a g.
optional int32 accel_peak_thousandths_g = 2;
+ // Duration of freefall in ms
+ optional int32 freefall_time_millis = 3;
}
/**
diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.cpp b/cmds/statsd/src/condition/CombinationConditionTracker.cpp
index 3661d2b..60a4b23 100644
--- a/cmds/statsd/src/condition/CombinationConditionTracker.cpp
+++ b/cmds/statsd/src/condition/CombinationConditionTracker.cpp
@@ -149,9 +149,9 @@
}
}
+ ConditionState newCondition =
+ evaluateCombinationCondition(mChildren, mLogicalOperation, nonSlicedConditionCache);
if (!mSliced) {
- ConditionState newCondition =
- evaluateCombinationCondition(mChildren, mLogicalOperation, nonSlicedConditionCache);
bool nonSlicedChanged = (mNonSlicedConditionState != newCondition);
mNonSlicedConditionState = newCondition;
@@ -172,7 +172,7 @@
break;
}
}
- nonSlicedConditionCache[mIndex] = ConditionState::kUnknown;
+ nonSlicedConditionCache[mIndex] = newCondition;
VLOG("CombinationPredicate %lld sliced may changed? %d", (long long)mConditionId,
conditionChangedCache[mIndex] == true);
}
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
index 73efb39..87104a3 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
@@ -289,9 +289,15 @@
// The event doesn't match this condition. So we just report existing condition values.
conditionChangedCache[mIndex] = false;
if (mSliced) {
- // if the condition result is sliced. metrics won't directly get value from the
- // cache, so just set any value other than kNotEvaluated.
+ // if the condition result is sliced. The overall condition is true if any of the sliced
+ // condition is true
conditionCache[mIndex] = mInitialValue;
+ for (const auto& slicedCondition : mSlicedConditionState) {
+ if (slicedCondition.second > 0) {
+ conditionCache[mIndex] = ConditionState::kTrue;
+ break;
+ }
+ }
} else {
const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY);
if (itr == mSlicedConditionState.end()) {
diff --git a/cmds/statsd/src/condition/StateTracker.cpp b/cmds/statsd/src/condition/StateTracker.cpp
index fe1740b..1965ce6 100644
--- a/cmds/statsd/src/condition/StateTracker.cpp
+++ b/cmds/statsd/src/condition/StateTracker.cpp
@@ -141,7 +141,7 @@
// one keys matched.
HashableDimensionKey primaryKey;
HashableDimensionKey state;
- if (!filterValues(mPrimaryKeys, event.getValues(), &primaryKey) ||
+ if ((mPrimaryKeys.size() > 0 && !filterValues(mPrimaryKeys, event.getValues(), &primaryKey)) ||
!filterValues(mOutputDimensions, event.getValues(), &state)) {
ALOGE("Failed to filter fields in the event?? panic now!");
conditionCache[mIndex] =
diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp
index f5310a4..ff25091 100644
--- a/cmds/statsd/src/config/ConfigManager.cpp
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -14,9 +14,13 @@
* limitations under the License.
*/
+#define DEBUG false // STOPSHIP if true
+#include "Log.h"
+
#include "config/ConfigManager.h"
#include "storage/StorageManager.h"
+#include "guardrail/StatsdStats.h"
#include "stats_util.h"
#include <android-base/file.h>
@@ -68,24 +72,37 @@
{
lock_guard <mutex> lock(mMutex);
- auto it = mConfigs.find(key);
-
const int numBytes = config.ByteSize();
vector<uint8_t> buffer(numBytes);
config.SerializeToArray(&buffer[0], numBytes);
- const bool isDuplicate =
- it != mConfigs.end() &&
- StorageManager::hasIdenticalConfig(key, buffer);
+ auto uidIt = mConfigs.find(key.GetUid());
+ // GuardRail: Limit the number of configs per uid.
+ if (uidIt != mConfigs.end()) {
+ auto it = uidIt->second.find(key);
+ if (it == uidIt->second.end() &&
+ uidIt->second.size() >= StatsdStats::kMaxConfigCountPerUid) {
+ ALOGE("ConfigManager: uid %d has exceeded the config count limit", key.GetUid());
+ return;
+ }
+ }
- // Update saved file on disk. We still update timestamp of file when
- // there exists a duplicate configuration to avoid garbage collection.
+ // Check if it's a duplicate config.
+ if (uidIt != mConfigs.end() && uidIt->second.find(key) != uidIt->second.end() &&
+ StorageManager::hasIdenticalConfig(key, buffer)) {
+ // This is a duplicate config.
+ ALOGI("ConfigManager This is a duplicate config %s", key.ToString().c_str());
+ // Update saved file on disk. We still update timestamp of file when
+ // there exists a duplicate configuration to avoid garbage collection.
+ update_saved_configs_locked(key, buffer, numBytes);
+ return;
+ }
+
+ // Update saved file on disk.
update_saved_configs_locked(key, buffer, numBytes);
- if (isDuplicate) return;
-
- // Add to set
- mConfigs.insert(key);
+ // Add to set.
+ mConfigs[key.GetUid()].insert(key);
for (sp<ConfigListener> listener : mListeners) {
broadcastList.push_back(listener);
@@ -113,11 +130,10 @@
{
lock_guard <mutex> lock(mMutex);
- auto it = mConfigs.find(key);
- if (it != mConfigs.end()) {
+ auto uidIt = mConfigs.find(key.GetUid());
+ if (uidIt != mConfigs.end() && uidIt->second.find(key) != uidIt->second.end()) {
// Remove from map
- mConfigs.erase(it);
-
+ uidIt->second.erase(key);
for (sp<ConfigListener> listener : mListeners) {
broadcastList.push_back(listener);
}
@@ -150,18 +166,20 @@
{
lock_guard <mutex> lock(mMutex);
- for (auto it = mConfigs.begin(); it != mConfigs.end();) {
+ auto uidIt = mConfigs.find(uid);
+ if (uidIt == mConfigs.end()) {
+ return;
+ }
+
+ for (auto it = uidIt->second.begin(); it != uidIt->second.end(); ++it) {
// Remove from map
- if (it->GetUid() == uid) {
remove_saved_configs(*it);
removed.push_back(*it);
mConfigReceivers.erase(*it);
- it = mConfigs.erase(it);
- } else {
- it++;
- }
}
+ mConfigs.erase(uidIt);
+
for (sp<ConfigListener> listener : mListeners) {
broadcastList.push_back(listener);
}
@@ -182,17 +200,16 @@
{
lock_guard <mutex> lock(mMutex);
-
- for (auto it = mConfigs.begin(); it != mConfigs.end();) {
- // Remove from map
- removed.push_back(*it);
- auto receiverIt = mConfigReceivers.find(*it);
- if (receiverIt != mConfigReceivers.end()) {
- mConfigReceivers.erase(*it);
+ for (auto uidIt = mConfigs.begin(); uidIt != mConfigs.end();) {
+ for (auto it = uidIt->second.begin(); it != uidIt->second.end();) {
+ // Remove from map
+ removed.push_back(*it);
+ it = uidIt->second.erase(it);
}
- it = mConfigs.erase(it);
+ uidIt = mConfigs.erase(uidIt);
}
+ mConfigReceivers.clear();
for (sp<ConfigListener> listener : mListeners) {
broadcastList.push_back(listener);
}
@@ -211,8 +228,10 @@
lock_guard<mutex> lock(mMutex);
vector<ConfigKey> ret;
- for (auto it = mConfigs.cbegin(); it != mConfigs.cend(); ++it) {
- ret.push_back(*it);
+ for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
+ for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
+ ret.push_back(*it);
+ }
}
return ret;
}
@@ -231,13 +250,15 @@
void ConfigManager::Dump(FILE* out) {
lock_guard<mutex> lock(mMutex);
- fprintf(out, "CONFIGURATIONS (%d)\n", (int)mConfigs.size());
+ fprintf(out, "CONFIGURATIONS\n");
fprintf(out, " uid name\n");
- for (const auto& key : mConfigs) {
- fprintf(out, " %6d %lld\n", key.GetUid(), (long long)key.GetId());
- auto receiverIt = mConfigReceivers.find(key);
- if (receiverIt != mConfigReceivers.end()) {
- fprintf(out, " -> received by PendingIntent as binder\n");
+ for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
+ for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
+ fprintf(out, " %6d %lld\n", it->GetUid(), (long long)it->GetId());
+ auto receiverIt = mConfigReceivers.find(*it);
+ if (receiverIt != mConfigReceivers.end()) {
+ fprintf(out, " -> received by PendingIntent as binder\n");
+ }
}
}
}
@@ -255,331 +276,6 @@
StorageManager::writeFile(file_name.c_str(), &buffer[0], numBytes);
}
-StatsdConfig build_fake_config() {
- // HACK: Hard code a test metric for counting screen on events...
- StatsdConfig config;
- config.set_id(12345);
-
- int WAKE_LOCK_TAG_ID = 1111; // put a fake id here to make testing easier.
- int WAKE_LOCK_UID_KEY_ID = 1;
- int WAKE_LOCK_NAME_KEY = 3;
- int WAKE_LOCK_STATE_KEY = 4;
- int WAKE_LOCK_ACQUIRE_VALUE = 1;
- int WAKE_LOCK_RELEASE_VALUE = 0;
-
- int APP_USAGE_TAG_ID = 12345;
- int APP_USAGE_UID_KEY_ID = 1;
- int APP_USAGE_STATE_KEY = 2;
- int APP_USAGE_FOREGROUND = 1;
- int APP_USAGE_BACKGROUND = 0;
-
- int SCREEN_EVENT_TAG_ID = 29;
- int SCREEN_EVENT_STATE_KEY = 1;
- int SCREEN_EVENT_ON_VALUE = 2;
- int SCREEN_EVENT_OFF_VALUE = 1;
-
- int UID_PROCESS_STATE_TAG_ID = 27;
- int UID_PROCESS_STATE_UID_KEY = 1;
-
- int KERNEL_WAKELOCK_TAG_ID = 1004;
- int KERNEL_WAKELOCK_COUNT_KEY = 2;
- int KERNEL_WAKELOCK_NAME_KEY = 1;
-
- int DEVICE_TEMPERATURE_TAG_ID = 33;
- int DEVICE_TEMPERATURE_KEY = 1;
-
- // Count Screen ON events.
- CountMetric* metric = config.add_count_metric();
- metric->set_id(1); // METRIC_1
- metric->set_what(102); // "SCREEN_TURNED_ON"
- metric->set_bucket(ONE_MINUTE);
-
- // Anomaly threshold for screen-on count.
- // TODO(b/70627390): Uncomment once the bug is fixed.
- /*Alert* alert = config.add_alert();
- alert->set_id("ALERT_1");
- alert->set_metric_name("METRIC_1");
- alert->set_number_of_buckets(6);
- alert->set_trigger_if_sum_gt(10);
- alert->set_refractory_period_secs(30);
- Alert::IncidentdDetails* details = alert->mutable_incidentd_details();
- details->add_section(12);
- details->add_section(13);*/
-
- config.add_allowed_log_source("AID_ROOT");
- config.add_allowed_log_source("AID_SYSTEM");
- config.add_allowed_log_source("AID_BLUETOOTH");
- config.add_allowed_log_source("com.android.statsd.dogfood");
- config.add_allowed_log_source("com.android.systemui");
-
- // Count process state changes, slice by uid.
- metric = config.add_count_metric();
- metric->set_id(2); // "METRIC_2"
- metric->set_what(104);
- metric->set_bucket(ONE_MINUTE);
- FieldMatcher* dimensions = metric->mutable_dimensions_in_what();
- dimensions->set_field(UID_PROCESS_STATE_TAG_ID);
- dimensions->add_child()->set_field(UID_PROCESS_STATE_UID_KEY);
-
- // Anomaly threshold for background count.
- // TODO(b/70627390): Uncomment once the bug is fixed.
- /*
- alert = config.add_alert();
- alert->set_id("ALERT_2");
- alert->set_metric_name("METRIC_2");
- alert->set_number_of_buckets(4);
- alert->set_trigger_if_sum_gt(30);
- alert->set_refractory_period_secs(20);
- details = alert->mutable_incidentd_details();
- details->add_section(14);
- details->add_section(15);*/
-
- // Count process state changes, slice by uid, while SCREEN_IS_OFF
- metric = config.add_count_metric();
- metric->set_id(3);
- metric->set_what(104);
- metric->set_bucket(ONE_MINUTE);
-
- dimensions = metric->mutable_dimensions_in_what();
- dimensions->set_field(UID_PROCESS_STATE_TAG_ID);
- dimensions->add_child()->set_field(UID_PROCESS_STATE_UID_KEY);
- metric->set_condition(202);
-
- // Count wake lock, slice by uid, while SCREEN_IS_ON and app in background
- metric = config.add_count_metric();
- metric->set_id(4);
- metric->set_what(107);
- metric->set_bucket(ONE_MINUTE);
- dimensions = metric->mutable_dimensions_in_what();
- dimensions->set_field(WAKE_LOCK_TAG_ID);
- dimensions->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
-
-
- metric->set_condition(204);
- MetricConditionLink* link = metric->add_links();
- link->set_condition(203);
- link->mutable_fields_in_what()->set_field(WAKE_LOCK_TAG_ID);
- link->mutable_fields_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
- link->mutable_fields_in_condition()->set_field(APP_USAGE_TAG_ID);
- link->mutable_fields_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
-
- // Duration of an app holding any wl, while screen on and app in background, slice by uid
- DurationMetric* durationMetric = config.add_duration_metric();
- durationMetric->set_id(5);
- durationMetric->set_bucket(ONE_MINUTE);
- durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
- dimensions = durationMetric->mutable_dimensions_in_what();
- dimensions->set_field(WAKE_LOCK_TAG_ID);
- dimensions->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
- durationMetric->set_what(205);
- durationMetric->set_condition(204);
- link = durationMetric->add_links();
- link->set_condition(203);
- link->mutable_fields_in_what()->set_field(WAKE_LOCK_TAG_ID);
- link->mutable_fields_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
- link->mutable_fields_in_condition()->set_field(APP_USAGE_TAG_ID);
- link->mutable_fields_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
-
- // max Duration of an app holding any wl, while screen on and app in background, slice by uid
- durationMetric = config.add_duration_metric();
- durationMetric->set_id(6);
- durationMetric->set_bucket(ONE_MINUTE);
- durationMetric->set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
- dimensions = durationMetric->mutable_dimensions_in_what();
- dimensions->set_field(WAKE_LOCK_TAG_ID);
- dimensions->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
- durationMetric->set_what(205);
- durationMetric->set_condition(204);
- link = durationMetric->add_links();
- link->set_condition(203);
- link->mutable_fields_in_what()->set_field(WAKE_LOCK_TAG_ID);
- link->mutable_fields_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
- link->mutable_fields_in_condition()->set_field(APP_USAGE_TAG_ID);
- link->mutable_fields_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
-
- // Duration of an app holding any wl, while screen on and app in background
- durationMetric = config.add_duration_metric();
- durationMetric->set_id(7);
- durationMetric->set_bucket(ONE_MINUTE);
- durationMetric->set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
- durationMetric->set_what(205);
- durationMetric->set_condition(204);
- link = durationMetric->add_links();
- link->set_condition(203);
- link->mutable_fields_in_what()->set_field(WAKE_LOCK_TAG_ID);
- link->mutable_fields_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
- link->mutable_fields_in_condition()->set_field(APP_USAGE_TAG_ID);
- link->mutable_fields_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
-
-
- // Duration of screen on time.
- durationMetric = config.add_duration_metric();
- durationMetric->set_id(8);
- durationMetric->set_bucket(ONE_MINUTE);
- durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
- durationMetric->set_what(201);
-
- // Anomaly threshold for background count.
- // TODO(b/70627390): Uncomment once the bug is fixed.
- /*
- alert = config.add_alert();
- alert->set_id(308);
- alert->set_metric_id(8);
- alert->set_number_of_buckets(4);
- alert->set_trigger_if_sum_gt(2000000000); // 2 seconds
- alert->set_refractory_period_secs(120);
- details = alert->mutable_incidentd_details();
- details->add_section(-1);*/
-
- // Value metric to count KERNEL_WAKELOCK when screen turned on
- ValueMetric* valueMetric = config.add_value_metric();
- valueMetric->set_id(11);
- valueMetric->set_what(109);
- valueMetric->mutable_value_field()->set_field(KERNEL_WAKELOCK_TAG_ID);
- valueMetric->mutable_value_field()->add_child()->set_field(KERNEL_WAKELOCK_COUNT_KEY);
- valueMetric->set_condition(201);
- dimensions = valueMetric->mutable_dimensions_in_what();
- dimensions->set_field(KERNEL_WAKELOCK_TAG_ID);
- dimensions->add_child()->set_field(KERNEL_WAKELOCK_NAME_KEY);
- // This is for testing easier. We should never set bucket size this small.
- durationMetric->set_bucket(ONE_MINUTE);
-
- // Add an EventMetric to log process state change events.
- EventMetric* eventMetric = config.add_event_metric();
- eventMetric->set_id(9);
- eventMetric->set_what(102); // "SCREEN_TURNED_ON"
-
- // Add an GaugeMetric.
- GaugeMetric* gaugeMetric = config.add_gauge_metric();
- gaugeMetric->set_id(10);
- gaugeMetric->set_what(101);
- auto gaugeFieldMatcher = gaugeMetric->mutable_gauge_fields_filter()->mutable_fields();
- gaugeFieldMatcher->set_field(DEVICE_TEMPERATURE_TAG_ID);
- gaugeFieldMatcher->add_child()->set_field(DEVICE_TEMPERATURE_KEY);
- durationMetric->set_bucket(ONE_MINUTE);
-
- // Event matchers.
- AtomMatcher* temperatureAtomMatcher = config.add_atom_matcher();
- temperatureAtomMatcher->set_id(101); // "DEVICE_TEMPERATURE"
- temperatureAtomMatcher->mutable_simple_atom_matcher()->set_atom_id(
- DEVICE_TEMPERATURE_TAG_ID);
-
- AtomMatcher* eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(102); // "SCREEN_TURNED_ON"
- SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(SCREEN_EVENT_TAG_ID);
- FieldValueMatcher* fieldValueMatcher = simpleAtomMatcher->add_field_value_matcher();
- fieldValueMatcher->set_field(SCREEN_EVENT_STATE_KEY);
- fieldValueMatcher->set_eq_int(SCREEN_EVENT_ON_VALUE);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(103); // "SCREEN_TURNED_OFF"
- simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(SCREEN_EVENT_TAG_ID);
- fieldValueMatcher = simpleAtomMatcher->add_field_value_matcher();
- fieldValueMatcher->set_field(SCREEN_EVENT_STATE_KEY);
- fieldValueMatcher->set_eq_int(SCREEN_EVENT_OFF_VALUE);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(104); // "PROCESS_STATE_CHANGE"
- simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(UID_PROCESS_STATE_TAG_ID);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(105); // "APP_GOES_BACKGROUND"
- simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(APP_USAGE_TAG_ID);
- fieldValueMatcher = simpleAtomMatcher->add_field_value_matcher();
- fieldValueMatcher->set_field(APP_USAGE_STATE_KEY);
- fieldValueMatcher->set_eq_int(APP_USAGE_BACKGROUND);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(106); // "APP_GOES_FOREGROUND"
- simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(APP_USAGE_TAG_ID);
- fieldValueMatcher = simpleAtomMatcher->add_field_value_matcher();
- fieldValueMatcher->set_field(APP_USAGE_STATE_KEY);
- fieldValueMatcher->set_eq_int(APP_USAGE_FOREGROUND);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(107); // "APP_GET_WL"
- simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(WAKE_LOCK_TAG_ID);
- fieldValueMatcher = simpleAtomMatcher->add_field_value_matcher();
- fieldValueMatcher->set_field(WAKE_LOCK_STATE_KEY);
- fieldValueMatcher->set_eq_int(WAKE_LOCK_ACQUIRE_VALUE);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(108); //"APP_RELEASE_WL"
- simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(WAKE_LOCK_TAG_ID);
- fieldValueMatcher = simpleAtomMatcher->add_field_value_matcher();
- fieldValueMatcher->set_field(WAKE_LOCK_STATE_KEY);
- fieldValueMatcher->set_eq_int(WAKE_LOCK_RELEASE_VALUE);
-
- // pulled events
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(109); // "KERNEL_WAKELOCK"
- simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(KERNEL_WAKELOCK_TAG_ID);
-
- // Predicates.............
- Predicate* predicate = config.add_predicate();
- predicate->set_id(201); // "SCREEN_IS_ON"
- SimplePredicate* simplePredicate = predicate->mutable_simple_predicate();
- simplePredicate->set_start(102); // "SCREEN_TURNED_ON"
- simplePredicate->set_stop(103);
- simplePredicate->set_count_nesting(false);
-
- predicate = config.add_predicate();
- predicate->set_id(202); // "SCREEN_IS_OFF"
- simplePredicate = predicate->mutable_simple_predicate();
- simplePredicate->set_start(103);
- simplePredicate->set_stop(102); // "SCREEN_TURNED_ON"
- simplePredicate->set_count_nesting(false);
-
- predicate = config.add_predicate();
- predicate->set_id(203); // "APP_IS_BACKGROUND"
- simplePredicate = predicate->mutable_simple_predicate();
- simplePredicate->set_start(105);
- simplePredicate->set_stop(106);
- FieldMatcher* predicate_dimension1 = simplePredicate->mutable_dimensions();
- predicate_dimension1->set_field(APP_USAGE_TAG_ID);
- predicate_dimension1->add_child()->set_field(APP_USAGE_UID_KEY_ID);
- simplePredicate->set_count_nesting(false);
-
- predicate = config.add_predicate();
- predicate->set_id(204); // "APP_IS_BACKGROUND_AND_SCREEN_ON"
- Predicate_Combination* combination_predicate = predicate->mutable_combination();
- combination_predicate->set_operation(LogicalOperation::AND);
- combination_predicate->add_predicate(203);
- combination_predicate->add_predicate(201);
-
- predicate = config.add_predicate();
- predicate->set_id(205); // "WL_HELD_PER_APP_PER_NAME"
- simplePredicate = predicate->mutable_simple_predicate();
- simplePredicate->set_start(107);
- simplePredicate->set_stop(108);
- FieldMatcher* predicate_dimension = simplePredicate->mutable_dimensions();
- predicate_dimension1->set_field(WAKE_LOCK_TAG_ID);
- predicate_dimension->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
- predicate_dimension->add_child()->set_field(WAKE_LOCK_NAME_KEY);
- simplePredicate->set_count_nesting(true);
-
- predicate = config.add_predicate();
- predicate->set_id(206); // "WL_HELD_PER_APP"
- simplePredicate = predicate->mutable_simple_predicate();
- simplePredicate->set_start(107);
- simplePredicate->set_stop(108);
- simplePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE);
- predicate_dimension = simplePredicate->mutable_dimensions();
- predicate_dimension->set_field(WAKE_LOCK_TAG_ID);
- predicate_dimension->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
- simplePredicate->set_count_nesting(true);
-
- return config;
-}
-
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/config/ConfigManager.h b/cmds/statsd/src/config/ConfigManager.h
index 9a38188a..611c342 100644
--- a/cmds/statsd/src/config/ConfigManager.h
+++ b/cmds/statsd/src/config/ConfigManager.h
@@ -36,9 +36,6 @@
/**
* Keeps track of which configurations have been set from various sources.
- *
- * TODO: Store the configs persistently too.
- * TODO: Dump method for debugging.
*/
class ConfigManager : public virtual android::RefBase {
public:
@@ -125,9 +122,9 @@
void remove_saved_configs(const ConfigKey& key);
/**
- * Config keys that have been set.
+ * Maps from uid to the config keys that have been set.
*/
- std::set<ConfigKey> mConfigs;
+ std::map<int, std::set<ConfigKey>> mConfigs;
/**
* Each config key can be subscribed by up to one receiver, specified as IBinder from
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 7675888..7f8755b 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -78,17 +78,17 @@
~StatsdStats(){};
// TODO: set different limit if the device is low ram.
- const static int kDimensionKeySizeSoftLimit = 300;
- const static int kDimensionKeySizeHardLimit = 500;
+ const static int kDimensionKeySizeSoftLimit = 500;
+ const static int kDimensionKeySizeHardLimit = 800;
// Per atom dimension key size limit
static const std::map<int, std::pair<size_t, size_t>> kAtomDimensionKeySizeLimitMap;
- const static int kMaxConfigCount = 10;
+ const static int kMaxConfigCountPerUid = 10;
const static int kMaxAlertCountPerConfig = 100;
- const static int kMaxConditionCountPerConfig = 200;
- const static int kMaxMetricCountPerConfig = 300;
- const static int kMaxMatcherCountPerConfig = 500;
+ const static int kMaxConditionCountPerConfig = 300;
+ const static int kMaxMetricCountPerConfig = 1000;
+ const static int kMaxMatcherCountPerConfig = 800;
// The max number of old config stats we keep.
const static int kMaxIceBoxSize = 20;
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 8e8a529..afa5140 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -117,7 +117,8 @@
}
}
-void CountMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
+void CountMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
+ const uint64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
}
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index ef738ac..fd9f0e0 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -61,7 +61,7 @@
void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
// Internal interface to handle sliced condition change.
- void onSlicedConditionMayChangeLocked(const uint64_t eventTime) override;
+ void onSlicedConditionMayChangeLocked(bool overallCondition, const uint64_t eventTime) override;
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index c6b9405..c28bb88 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -169,7 +169,8 @@
// 1. If combination condition, logical operation is AND, only one sliced child predicate.
// 2. No condition in dimension
// 3. The links covers all dimension fields in the sliced child condition predicate.
-void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt1(const uint64_t eventTime) {
+void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt1(bool condition,
+ const uint64_t eventTime) {
if (mMetric2ConditionLinks.size() != 1 ||
!mHasLinksToAllConditionDimensionsInTracker ||
!mDimensionsInCondition.empty()) {
@@ -241,7 +242,8 @@
// SlicedConditionChange optimization case 2:
// 1. If combination condition, logical operation is AND, only one sliced child predicate.
// 2. Has dimensions_in_condition and it equals to the output dimensions of the sliced predicate.
-void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt2(const uint64_t eventTime) {
+void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt2(bool condition,
+ const uint64_t eventTime) {
if (mMetric2ConditionLinks.size() > 1 || !mSameConditionDimensionsInTracker) {
return;
}
@@ -322,7 +324,8 @@
}
}
-void DurationMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
+void DurationMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
+ const uint64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
flushIfNeededLocked(eventTime);
@@ -333,20 +336,20 @@
bool changeDimTrackable = mWizard->IsChangedDimensionTrackable(mConditionTrackerIndex);
if (changeDimTrackable && mHasLinksToAllConditionDimensionsInTracker &&
mDimensionsInCondition.empty()) {
- onSlicedConditionMayChangeLocked_opt1(eventTime);
+ onSlicedConditionMayChangeLocked_opt1(overallCondition, eventTime);
return;
}
if (changeDimTrackable && mSameConditionDimensionsInTracker &&
mMetric2ConditionLinks.size() <= 1) {
- onSlicedConditionMayChangeLocked_opt2(eventTime);
+ onSlicedConditionMayChangeLocked_opt2(overallCondition, eventTime);
return;
}
// Now for each of the on-going event, check if the condition has changed for them.
for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
for (auto& pair : whatIt.second) {
- pair.second->onSlicedConditionMayChange(eventTime);
+ pair.second->onSlicedConditionMayChange(overallCondition, eventTime);
}
}
@@ -372,7 +375,7 @@
if (newTracker != nullptr) {
newTracker->setEventKey(MetricDimensionKey(
whatIt.first, conditionDimension));
- newTracker->onSlicedConditionMayChange(eventTime);
+ newTracker->onSlicedConditionMayChange(overallCondition, eventTime);
whatIt.second[conditionDimension] = std::move(newTracker);
}
}
@@ -398,7 +401,7 @@
if (newTracker != nullptr) {
newTracker->setEventKey(
MetricDimensionKey(whatIt.first, conditionDimension));
- newTracker->onSlicedConditionMayChange(eventTime);
+ newTracker->onSlicedConditionMayChange(overallCondition, eventTime);
whatIt.second[conditionDimension] = std::move(newTracker);
}
}
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 985749d..75f2391 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -68,10 +68,10 @@
void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
// Internal interface to handle sliced condition change.
- void onSlicedConditionMayChangeLocked(const uint64_t eventTime) override;
+ void onSlicedConditionMayChangeLocked(bool overallCondition, const uint64_t eventTime) override;
- void onSlicedConditionMayChangeLocked_opt1(const uint64_t eventTime);
- void onSlicedConditionMayChangeLocked_opt2(const uint64_t eventTime);
+ void onSlicedConditionMayChangeLocked_opt1(bool overallCondition, const uint64_t eventTime);
+ void onSlicedConditionMayChangeLocked_opt2(bool overallCondition, const uint64_t eventTime);
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index bd8b293..42a5a3a 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -79,7 +79,8 @@
mProto->clear();
}
-void EventMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
+void EventMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
+ const uint64_t eventTime) {
}
std::unique_ptr<std::vector<uint8_t>> serializeProtoLocked(ProtoOutputStream& protoOutput) {
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index d6f81fd..93c6c9a 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -53,7 +53,7 @@
void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
// Internal interface to handle sliced condition change.
- void onSlicedConditionMayChangeLocked(const uint64_t eventTime) override;
+ void onSlicedConditionMayChangeLocked(bool overallCondition, const uint64_t eventTime) override;
void dropDataLocked(const uint64_t dropTimeNs) override;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index f08d54a..f0e0df1 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -115,8 +115,9 @@
mStatsPullerManager->RegisterReceiver(mPullTagId, this, bucketSizeMills);
}
- VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
- (long long)mBucketSizeNs, (long long)mStartTimeNs);
+ VLOG("Gauge metric %lld created. bucket size %lld start_time: %lld sliced %d",
+ (long long)metric.id(), (long long)mBucketSizeNs, (long long)mStartTimeNs,
+ mConditionSliced);
}
// for testing
@@ -155,7 +156,7 @@
void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
ProtoOutputStream* protoOutput) {
- VLOG("gauge metric %lld report now...", (long long)mMetricId);
+ VLOG("Gauge metric %lld report now...", (long long)mMetricId);
flushIfNeededLocked(dumpTimeNs);
if (mPastBuckets.empty()) {
@@ -168,7 +169,7 @@
for (const auto& pair : mPastBuckets) {
const MetricDimensionKey& dimensionKey = pair.first;
- VLOG(" dimension key %s", dimensionKey.toString().c_str());
+ VLOG("Gauge dimension key %s", dimensionKey.toString().c_str());
uint64_t wrapperToken =
protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
@@ -221,8 +222,9 @@
}
}
protoOutput->end(bucketInfoToken);
- VLOG("\t bucket [%lld - %lld] includes %d atoms.", (long long)bucket.mBucketStartNs,
- (long long)bucket.mBucketEndNs, (int)bucket.mGaugeAtoms.size());
+ VLOG("Gauge \t bucket [%lld - %lld] includes %d atoms.",
+ (long long)bucket.mBucketStartNs, (long long)bucket.mBucketEndNs,
+ (int)bucket.mGaugeAtoms.size());
}
protoOutput->end(wrapperToken);
}
@@ -233,27 +235,6 @@
}
void GaugeMetricProducer::pullLocked() {
- vector<std::shared_ptr<LogEvent>> allData;
- if (!mStatsPullerManager->Pull(mPullTagId, &allData)) {
- ALOGE("Stats puller failed for tag: %d", mPullTagId);
- return;
- }
- for (const auto& data : allData) {
- onMatchedLogEventLocked(0, *data);
- }
-}
-
-void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet,
- const uint64_t eventTime) {
- VLOG("Metric %lld onConditionChanged", (long long)mMetricId);
- flushIfNeededLocked(eventTime);
- mCondition = conditionMet;
-
- // Push mode. No need to proactively pull the gauge data.
- if (mPullTagId == -1) {
- return;
- }
-
bool triggerPuller = false;
switch(mSamplingType) {
// When the metric wants to do random sampling and there is already one gauge atom for the
@@ -275,17 +256,37 @@
vector<std::shared_ptr<LogEvent>> allData;
if (!mStatsPullerManager->Pull(mPullTagId, &allData)) {
- ALOGE("Stats puller failed for tag: %d", mPullTagId);
+ ALOGE("Gauge Stats puller failed for tag: %d", mPullTagId);
return;
}
+
for (const auto& data : allData) {
onMatchedLogEventLocked(0, *data);
}
- flushIfNeededLocked(eventTime);
}
-void GaugeMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
- VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
+void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet,
+ const uint64_t eventTime) {
+ VLOG("GaugeMetric %lld onConditionChanged", (long long)mMetricId);
+ flushIfNeededLocked(eventTime);
+ mCondition = conditionMet;
+
+ if (mPullTagId != -1) {
+ pullLocked();
+ } // else: Push mode. No need to proactively pull the gauge data.
+}
+
+void GaugeMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
+ const uint64_t eventTime) {
+ VLOG("GaugeMetric %lld onSlicedConditionMayChange overall condition %d", (long long)mMetricId,
+ overallCondition);
+ flushIfNeededLocked(eventTime);
+ // If the condition is sliced, mCondition is true if any of the dimensions is true. And we will
+ // pull for every dimension.
+ mCondition = overallCondition;
+ if (mPullTagId != -1) {
+ pullLocked();
+ } // else: Push mode. No need to proactively pull the gauge data.
}
std::shared_ptr<vector<FieldValue>> GaugeMetricProducer::getGaugeFields(const LogEvent& event) {
@@ -337,7 +338,7 @@
uint64_t eventTimeNs = event.GetElapsedTimestampNs();
mTagId = event.GetTagId();
if (eventTimeNs < mCurrentBucketStartTimeNs) {
- VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
+ VLOG("Gauge Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
(long long)mCurrentBucketStartTimeNs);
return;
}
@@ -403,8 +404,8 @@
uint64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
if (eventTimeNs < currentBucketEndTimeNs) {
- VLOG("eventTime is %lld, less than next bucket start time %lld", (long long)eventTimeNs,
- (long long)(mCurrentBucketStartTimeNs + mBucketSizeNs));
+ VLOG("Gauge eventTime is %lld, less than next bucket start time %lld",
+ (long long)eventTimeNs, (long long)(mCurrentBucketStartTimeNs + mBucketSizeNs));
return;
}
@@ -414,7 +415,7 @@
int64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
mCurrentBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
mCurrentBucketNum += numBucketsForward;
- VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
+ VLOG("Gauge metric %lld: new bucket start time: %lld", (long long)mMetricId,
(long long)mCurrentBucketStartTimeNs);
}
@@ -433,7 +434,7 @@
info.mGaugeAtoms = slice.second;
auto& bucketList = mPastBuckets[slice.first];
bucketList.push_back(info);
- VLOG("gauge metric %lld, dump key value: %s", (long long)mMetricId,
+ VLOG("Gauge gauge metric %lld, dump key value: %s", (long long)mMetricId,
slice.first.toString().c_str());
}
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 4b543f8..9605b13 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -100,7 +100,7 @@
void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
// Internal interface to handle sliced condition change.
- void onSlicedConditionMayChangeLocked(const uint64_t eventTime) override;
+ void onSlicedConditionMayChangeLocked(bool overallCondition, const uint64_t eventTime) override;
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
@@ -155,6 +155,7 @@
const size_t mDimensionHardLimit;
FRIEND_TEST(GaugeMetricProducerTest, TestWithCondition);
+ FRIEND_TEST(GaugeMetricProducerTest, TestWithSlicedCondition);
FRIEND_TEST(GaugeMetricProducerTest, TestNoCondition);
FRIEND_TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade);
FRIEND_TEST(GaugeMetricProducerTest, TestPulledWithUpgrade);
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index f4495a1..bf529c8 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -33,7 +33,6 @@
bool condition;
ConditionKey conditionKey;
-
std::unordered_set<HashableDimensionKey> dimensionKeysInCondition;
if (mConditionSliced) {
for (const auto& link : mMetric2ConditionLinks) {
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 4983f96..0b3d677 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -98,9 +98,9 @@
onConditionChangedLocked(condition, eventTime);
}
- void onSlicedConditionMayChange(const uint64_t eventTime) {
+ void onSlicedConditionMayChange(bool overallCondition, const uint64_t eventTime) {
std::lock_guard<std::mutex> lock(mMutex);
- onSlicedConditionMayChangeLocked(eventTime);
+ onSlicedConditionMayChangeLocked(overallCondition, eventTime);
}
bool isConditionSliced() const {
@@ -163,7 +163,8 @@
protected:
virtual void onConditionChangedLocked(const bool condition, const uint64_t eventTime) = 0;
- virtual void onSlicedConditionMayChangeLocked(const uint64_t eventTime) = 0;
+ virtual void onSlicedConditionMayChangeLocked(bool overallCondition,
+ const uint64_t eventTime) = 0;
virtual void onDumpReportLocked(const uint64_t dumpTimeNs,
android::util::ProtoOutputStream* protoOutput) = 0;
virtual size_t byteSizeLocked() const = 0;
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index c773d4f..1be082a 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -326,7 +326,8 @@
// notification, and the metric can query the sliced conditions that are
// interesting to it.
} else {
- mAllMetricProducers[metricIndex]->onSlicedConditionMayChange(eventTime);
+ mAllMetricProducers[metricIndex]->onSlicedConditionMayChange(conditionCache[i],
+ eventTime);
}
}
}
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index ed4d7e4..e19e236 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -134,7 +134,8 @@
}
}
-void ValueMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
+void ValueMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
+ const uint64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
}
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index c4477b3..796e83a 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -93,7 +93,7 @@
void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
// Internal interface to handle sliced condition change.
- void onSlicedConditionMayChangeLocked(const uint64_t eventTime) override;
+ void onSlicedConditionMayChangeLocked(bool overallCondition, const uint64_t eventTime) override;
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index ddfb8cc..4132703 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -92,7 +92,7 @@
const bool stopAll) = 0;
virtual void noteStopAll(const uint64_t eventTime) = 0;
- virtual void onSlicedConditionMayChange(const uint64_t timestamp) = 0;
+ virtual void onSlicedConditionMayChange(bool overallCondition, const uint64_t timestamp) = 0;
virtual void onConditionChanged(bool condition, const uint64_t timestamp) = 0;
// Flush stale buckets if needed, and return true if the tracker has no on-going duration
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
index df9e6ae..15d9619 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
@@ -245,7 +245,8 @@
return flushCurrentBucket(eventTimeNs, output);
}
-void MaxDurationTracker::onSlicedConditionMayChange(const uint64_t timestamp) {
+void MaxDurationTracker::onSlicedConditionMayChange(bool overallCondition,
+ const uint64_t timestamp) {
// Now for each of the on-going event, check if the condition has changed for them.
for (auto& pair : mInfos) {
if (pair.second.state == kStopped) {
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
index 32d42fa..884e8ac 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
@@ -53,7 +53,7 @@
const uint64_t& eventTimeNs,
std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>*) override;
- void onSlicedConditionMayChange(const uint64_t timestamp) override;
+ void onSlicedConditionMayChange(bool overallCondition, const uint64_t timestamp) override;
void onConditionChanged(bool condition, const uint64_t timestamp) override;
int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
index da79217..50db9a0 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
@@ -214,7 +214,8 @@
return flushCurrentBucket(eventTimeNs, output);
}
-void OringDurationTracker::onSlicedConditionMayChange(const uint64_t timestamp) {
+void OringDurationTracker::onSlicedConditionMayChange(bool overallCondition,
+ const uint64_t timestamp) {
vector<pair<HashableDimensionKey, int>> startedToPaused;
vector<pair<HashableDimensionKey, int>> pausedToStarted;
if (!mStarted.empty()) {
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
index ca8abfe..987e28e 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
@@ -45,7 +45,7 @@
const bool stopAll) override;
void noteStopAll(const uint64_t eventTime) override;
- void onSlicedConditionMayChange(const uint64_t timestamp) override;
+ void onSlicedConditionMayChange(bool overallCondition, const uint64_t timestamp) override;
void onConditionChanged(bool condition, const uint64_t timestamp) override;
bool flushCurrentBucket(
diff --git a/cmds/statsd/tests/ConfigManager_test.cpp b/cmds/statsd/tests/ConfigManager_test.cpp
index 90c3a2f..838745e 100644
--- a/cmds/statsd/tests/ConfigManager_test.cpp
+++ b/cmds/statsd/tests/ConfigManager_test.cpp
@@ -64,16 +64,6 @@
const int64_t testConfigId = 12345;
-TEST(ConfigManagerTest, TestFakeConfig) {
- auto metricsManager = std::make_unique<MetricsManager>(
- ConfigKey(0, testConfigId), build_fake_config(), 1000, new UidMap(),
- new AlarmMonitor(10, [](const sp<IStatsCompanionService>&, int64_t){},
- [](const sp<IStatsCompanionService>&){}),
- new AlarmMonitor(10, [](const sp<IStatsCompanionService>&, int64_t){},
- [](const sp<IStatsCompanionService>&){}));
- EXPECT_TRUE(metricsManager->isConfigValid());
-}
-
/**
* Test the addOrUpdate and remove methods
*/
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index a75d6c8..2583c95 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -338,6 +338,82 @@
->mValue.int_value);
}
+TEST(GaugeMetricProducerTest, TestWithSlicedCondition) {
+ const int conditionTag = 65;
+ GaugeMetric metric;
+ metric.set_id(1111111);
+ metric.set_bucket(ONE_MINUTE);
+ metric.mutable_gauge_fields_filter()->set_include_all(true);
+ metric.set_condition(StringToId("APP_DIED"));
+ auto dim = metric.mutable_dimensions_in_what();
+ dim->set_field(tagId);
+ dim->add_child()->set_field(1);
+
+ dim = metric.mutable_dimensions_in_condition();
+ dim->set_field(conditionTag);
+ dim->add_child()->set_field(1);
+
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ EXPECT_CALL(*wizard, query(_, _, _, _, _, _))
+ .WillRepeatedly(
+ Invoke([](const int conditionIndex, const ConditionKey& conditionParameters,
+ const vector<Matcher>& dimensionFields, const bool isSubsetDim,
+ const bool isPartialLink,
+ std::unordered_set<HashableDimensionKey>* dimensionKeySet) {
+ dimensionKeySet->clear();
+ int pos[] = {1, 0, 0};
+ Field f(conditionTag, pos, 0);
+ HashableDimensionKey key;
+ key.mutableValues()->emplace_back(f, Value((int32_t)1000000));
+ dimensionKeySet->insert(key);
+
+ return ConditionState::kTrue;
+ }));
+
+ shared_ptr<MockStatsPullerManager> pullerManager =
+ make_shared<StrictMock<MockStatsPullerManager>>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ event->write(1000);
+ event->write(100);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
+ pullerManager);
+ gaugeProducer.setBucketSize(60 * NS_PER_SEC);
+
+ gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
+
+ EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+ const auto& key = gaugeProducer.mCurrentSlicedBucket->begin()->first;
+ EXPECT_EQ(1UL, key.getDimensionKeyInWhat().getValues().size());
+ EXPECT_EQ(1000, key.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+
+ EXPECT_EQ(1UL, key.getDimensionKeyInCondition().getValues().size());
+ EXPECT_EQ(1000000, key.getDimensionKeyInCondition().getValues()[0].mValue.int_value);
+
+ EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+ event->write(1000);
+ event->write(110);
+ event->init();
+ allData.push_back(event);
+ gaugeProducer.onDataPulled(allData);
+
+ EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+ EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+}
+
TEST(GaugeMetricProducerTest, TestAnomalyDetection) {
sp<AlarmMonitor> alarmMonitor;
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
diff --git a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
index 13cdb0b..817dcae 100644
--- a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
@@ -209,7 +209,7 @@
tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
- tracker.onSlicedConditionMayChange(eventStartTimeNs + 5);
+ tracker.onSlicedConditionMayChange(true, eventStartTimeNs + 5);
tracker.noteStop(kEventKey1, eventStartTimeNs + durationTimeNs, false);
@@ -249,9 +249,9 @@
tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
// condition to false; record duration 5n
- tracker.onSlicedConditionMayChange(eventStartTimeNs + 5);
+ tracker.onSlicedConditionMayChange(true, eventStartTimeNs + 5);
// condition to true.
- tracker.onSlicedConditionMayChange(eventStartTimeNs + 1000);
+ tracker.onSlicedConditionMayChange(true, eventStartTimeNs + 1000);
// 2nd duration: 1000ns
tracker.noteStop(kEventKey1, eventStartTimeNs + durationTimeNs, false);
@@ -291,7 +291,7 @@
tracker.noteStop(kEventKey1, eventStartTimeNs + 3, false);
- tracker.onSlicedConditionMayChange(eventStartTimeNs + 15);
+ tracker.onSlicedConditionMayChange(true, eventStartTimeNs + 15);
tracker.noteStop(kEventKey1, eventStartTimeNs + 2003, false);
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 8e2e43c..3af6105 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -369,6 +369,7 @@
Landroid/bluetooth/BluetoothGatt;->mAuthRetryState:I
Landroid/bluetooth/BluetoothGatt;->refresh()Z
Landroid/bluetooth/BluetoothHeadset;->close()V
+Landroid/bluetooth/BluetoothMapClient;->sendMessage(Landroid/bluetooth/BluetoothDevice;[Landroid/net/Uri;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;)Z
Landroid/bluetooth/BluetoothPan;->isTetheringOn()Z
Landroid/bluetooth/BluetoothPan;->setBluetoothTethering(Z)V
Landroid/bluetooth/BluetoothUuid;->RESERVED_UUIDS:[Landroid/os/ParcelUuid;
@@ -1109,6 +1110,7 @@
Landroid/net/wifi/p2p/WifiP2pManager;->deletePersistentGroup(Landroid/net/wifi/p2p/WifiP2pManager$Channel;ILandroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
Landroid/net/wifi/p2p/WifiP2pManager;->requestPersistentGroupInfo(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Landroid/net/wifi/p2p/WifiP2pManager$PersistentGroupInfoListener;)V
Landroid/net/wifi/p2p/WifiP2pManager;->setDeviceName(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Ljava/lang/String;Landroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
+Landroid/net/wifi/p2p/WifiP2pManager;->setWifiP2pChannels(Landroid/net/wifi/p2p/WifiP2pManager$Channel;IILandroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
Landroid/net/wifi/ScanResult;->anqpDomainId:I
Landroid/net/wifi/ScanResult;->anqpLines:Ljava/util/List;
Landroid/net/wifi/ScanResult;->distanceCm:I
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index 2f0bba1..77bb0bb 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -32,6 +32,7 @@
Landroid/app/IActivityManager;->getTaskSnapshot(IZ)Landroid/app/ActivityManager$TaskSnapshot;
Landroid/app/IActivityManager;->registerTaskStackListener(Landroid/app/ITaskStackListener;)V
Landroid/app/IActivityManager;->removeTask(I)Z
+Landroid/app/IActivityManager;->requestBugReport(I)V
Landroid/app/IActivityManager;->startActivityAsUser(Landroid/app/IApplicationThread;Ljava/lang/String;Landroid/content/Intent;Ljava/lang/String;Landroid/os/IBinder;Ljava/lang/String;IILandroid/app/ProfilerInfo;Landroid/os/Bundle;I)I
Landroid/app/IActivityManager;->startActivityFromRecents(ILandroid/os/Bundle;)I
Landroid/app/IActivityManager;->startActivity(Landroid/app/IApplicationThread;Ljava/lang/String;Landroid/content/Intent;Ljava/lang/String;Landroid/os/IBinder;Ljava/lang/String;IILandroid/app/ProfilerInfo;Landroid/os/Bundle;)I
@@ -42,6 +43,7 @@
Landroid/app/IAssistDataReceiver;->onHandleAssistScreenshot(Landroid/graphics/Bitmap;)V
Landroid/app/IAssistDataReceiver$Stub;-><init>()V
Landroid/app/KeyguardManager;->isDeviceLocked(I)Z
+Landroid/app/NotificationManager;->cancelAsUser(Ljava/lang/String;ILandroid/os/UserHandle;)V
Landroid/app/StatusBarManager;->removeIcon(Ljava/lang/String;)V
Landroid/app/StatusBarManager;->setIcon(Ljava/lang/String;IILjava/lang/String;)V
Landroid/app/TaskStackListener;->onActivityDismissingDockedStack()V
@@ -106,6 +108,11 @@
Landroid/graphics/Bitmap;->createHardwareBitmap(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;
Landroid/graphics/Canvas;->clipRegion(Landroid/graphics/Region;Landroid/graphics/Region$Op;)Z
Landroid/graphics/Canvas;->clipRegion(Landroid/graphics/Region;)Z
+Landroid/graphics/Canvas;->save(I)I
+Landroid/graphics/Canvas;->saveLayerAlpha(FFFFII)I
+Landroid/graphics/Canvas;->saveLayerAlpha(Landroid/graphics/RectF;II)I
+Landroid/graphics/Canvas;->saveLayer(FFFFLandroid/graphics/Paint;I)I
+Landroid/graphics/Canvas;->saveLayer(Landroid/graphics/RectF;Landroid/graphics/Paint;I)I
Landroid/graphics/drawable/Drawable;->isProjected()Z
Landroid/graphics/drawable/Drawable;->updateTintFilter(Landroid/graphics/PorterDuffColorFilter;Landroid/content/res/ColorStateList;Landroid/graphics/PorterDuff$Mode;)Landroid/graphics/PorterDuffColorFilter;
Landroid/hardware/camera2/CaptureRequest$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
@@ -308,6 +315,7 @@
Landroid/net/SntpClient;->getNtpTime()J
Landroid/net/SntpClient;->getNtpTimeReference()J
Landroid/net/SntpClient;->getRoundTripTime()J
+Landroid/net/SntpClient;->requestTime(Ljava/lang/String;I)Z
Landroid/net/StaticIpConfiguration;->dnsServers:Ljava/util/ArrayList;
Landroid/net/StaticIpConfiguration;->domains:Ljava/lang/String;
Landroid/net/StaticIpConfiguration;->gateway:Ljava/net/InetAddress;
@@ -402,6 +410,9 @@
Landroid/service/dreams/DreamService;->isDozing()Z
Landroid/service/dreams/DreamService;->startDozing()V
Landroid/service/dreams/DreamService;->stopDozing()V
+Landroid/service/euicc/EuiccProfileInfo;-><init>(Ljava/lang/String;[Landroid/telephony/UiccAccessRule;Ljava/lang/String;)V
+Landroid/service/euicc/GetDefaultDownloadableSubscriptionListResult;->result:I
+Landroid/service/euicc/GetDownloadableSubscriptionMetadataResult;->result:I
Landroid/service/vr/VrListenerService;->onCurrentVrActivityChanged(Landroid/content/ComponentName;ZI)V
Landroid/system/NetlinkSocketAddress;-><init>(II)V
Landroid/system/Os;->bind(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V
@@ -418,16 +429,42 @@
Landroid/telecom/ParcelableCall;->getId()Ljava/lang/String;
Landroid/telecom/TelecomManager;->from(Landroid/content/Context;)Landroid/telecom/TelecomManager;
Landroid/telecom/VideoProfile$CameraCapabilities;-><init>(IIZF)V
+Landroid/telephony/euicc/DownloadableSubscription;->encodedActivationCode:Ljava/lang/String;
+Landroid/telephony/euicc/DownloadableSubscription;->setAccessRules([Landroid/telephony/UiccAccessRule;)V
+Landroid/telephony/euicc/DownloadableSubscription;->setCarrierName(Ljava/lang/String;)V
+Landroid/telephony/ims/compat/feature/ImsFeature;->getFeatureState()I
+Landroid/telephony/ims/compat/feature/ImsFeature;->setFeatureState(I)V
Landroid/telephony/ims/compat/feature/MMTelFeature;-><init>()V
Landroid/telephony/ims/compat/ImsService;-><init>()V
+Landroid/telephony/ims/compat/ImsService;->mImsServiceController:Landroid/os/IBinder;
Landroid/telephony/ims/compat/stub/ImsCallSessionImplBase;-><init>()V
+Landroid/telephony/ims/compat/stub/ImsConfigImplBase;->getIImsConfig()Lcom/android/ims/internal/IImsConfig;
Landroid/telephony/ims/compat/stub/ImsConfigImplBase;-><init>(Landroid/content/Context;)V
Landroid/telephony/ims/compat/stub/ImsUtListenerImplBase;-><init>()V
Landroid/telephony/ims/ImsCallForwardInfo;-><init>()V
+Landroid/telephony/ims/ImsCallForwardInfo;->mCondition:I
+Landroid/telephony/ims/ImsCallForwardInfo;->mNumber:Ljava/lang/String;
+Landroid/telephony/ims/ImsCallForwardInfo;->mServiceClass:I
+Landroid/telephony/ims/ImsCallForwardInfo;->mStatus:I
+Landroid/telephony/ims/ImsCallForwardInfo;->mTimeSeconds:I
+Landroid/telephony/ims/ImsCallForwardInfo;->mToA:I
+Landroid/telephony/ims/ImsCallProfile;->mCallExtras:Landroid/os/Bundle;
+Landroid/telephony/ims/ImsCallProfile;->mCallType:I
+Landroid/telephony/ims/ImsCallProfile;->mMediaProfile:Landroid/telephony/ims/ImsStreamMediaProfile;
+Landroid/telephony/ims/ImsCallProfile;->mRestrictCause:I
Landroid/telephony/ims/ImsCallProfile;->presentationToOIR(I)I
Landroid/telephony/ims/ImsExternalCallState;-><init>(ILandroid/net/Uri;ZIIZ)V
Landroid/telephony/ims/ImsReasonInfo;-><init>(II)V
+Landroid/telephony/ims/ImsReasonInfo;->mCode:I
+Landroid/telephony/ims/ImsReasonInfo;->mExtraCode:I
+Landroid/telephony/ims/ImsReasonInfo;->mExtraMessage:Ljava/lang/String;
+Landroid/telephony/ims/ImsSsInfo;->mIcbNum:Ljava/lang/String;
+Landroid/telephony/ims/ImsSsInfo;->mStatus:I
Landroid/telephony/ims/ImsStreamMediaProfile;-><init>()V
+Landroid/telephony/ims/ImsStreamMediaProfile;->mAudioDirection:I
+Landroid/telephony/ims/ImsStreamMediaProfile;->mAudioQuality:I
+Landroid/telephony/ims/ImsStreamMediaProfile;->mVideoDirection:I
+Landroid/telephony/ims/ImsVideoCallProvider;->getInterface()Lcom/android/ims/internal/IImsVideoCallProvider;
Landroid/telephony/mbms/IMbmsStreamingSessionCallback$Stub;-><init>()V
Landroid/telephony/mbms/IStreamingServiceCallback$Stub;-><init>()V
Landroid/telephony/mbms/vendor/IMbmsStreamingService;->getPlaybackUri(ILjava/lang/String;)Landroid/net/Uri;
@@ -449,6 +486,7 @@
Landroid/telephony/Rlog;->e(Ljava/lang/String;Ljava/lang/String;)I
Landroid/telephony/Rlog;->e(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
Landroid/telephony/Rlog;->i(Ljava/lang/String;Ljava/lang/String;)I
+Landroid/telephony/ServiceState;->bitmaskHasTech(II)Z
Landroid/telephony/ServiceState;->getDataRegState()I
Landroid/telephony/ServiceState;->getDataRoaming()Z
Landroid/telephony/ServiceState;->getRilDataRadioTechnology()I
@@ -475,12 +513,19 @@
Landroid/telephony/SubscriptionManager;->setDisplayName(Ljava/lang/String;IJ)I
Landroid/telephony/SubscriptionManager;->setIconTint(II)I
Landroid/telephony/TelephonyManager;->getIntAtIndex(Landroid/content/ContentResolver;Ljava/lang/String;I)I
+Landroid/telephony/TelephonyManager;->getIsimDomain()Ljava/lang/String;
Landroid/telephony/TelephonyManager;->getNetworkTypeName()Ljava/lang/String;
+Landroid/telephony/TelephonyManager;->getPreferredNetworkType(I)I
+Landroid/telephony/TelephonyManager;->getServiceStateForSubscriber(I)Landroid/telephony/ServiceState;
Landroid/telephony/TelephonyManager;->getVoiceMessageCount()I
Landroid/telephony/TelephonyManager;->getVoiceNetworkType(I)I
+Landroid/telephony/TelephonyManager;->isImsRegistered()Z
+Landroid/telephony/TelephonyManager;->isWifiCallingAvailable()Z
Landroid/telephony/TelephonyManager$MultiSimVariants;->DSDA:Landroid/telephony/TelephonyManager$MultiSimVariants;
Landroid/telephony/TelephonyManager$MultiSimVariants;->DSDS:Landroid/telephony/TelephonyManager$MultiSimVariants;
+Landroid/telephony/TelephonyManager;->nvResetConfig(I)Z
Landroid/telephony/TelephonyManager;->putIntAtIndex(Landroid/content/ContentResolver;Ljava/lang/String;II)Z
+Landroid/telephony/TelephonyManager;->setPreferredNetworkType(II)Z
Landroid/text/TextUtils;->isPrintableAsciiOnly(Ljava/lang/CharSequence;)Z
Landroid/util/FloatMath;->ceil(F)F
Landroid/util/FloatMath;->cos(F)F
@@ -498,6 +543,8 @@
Landroid/util/LongArray;->get(I)J
Landroid/util/LongArray;-><init>()V
Landroid/util/LongArray;->size()I
+Landroid/util/RecurrenceRule;->buildRecurringMonthly(ILjava/time/ZoneId;)Landroid/util/RecurrenceRule;
+Landroid/util/RecurrenceRule;->start:Ljava/time/ZonedDateTime;
Landroid/util/Slog;->e(Ljava/lang/String;Ljava/lang/String;)I
Landroid/util/Slog;->e(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
Landroid/util/Slog;->println(ILjava/lang/String;Ljava/lang/String;)I
@@ -586,6 +633,7 @@
Lcom/android/ims/internal/IImsCallSessionListener;->callSessionTtyModeReceived(Lcom/android/ims/internal/IImsCallSession;I)V
Lcom/android/ims/internal/IImsCallSessionListener;->callSessionUpdated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V
Lcom/android/ims/internal/IImsRegistrationListener;->registrationAssociatedUriChanged([Landroid/net/Uri;)V
+Lcom/android/ims/internal/IImsRegistrationListener;->registrationChangeFailed(ILandroid/telephony/ims/ImsReasonInfo;)V
Lcom/android/ims/internal/IImsRegistrationListener;->registrationConnectedWithRadioTech(I)V
Lcom/android/ims/internal/IImsRegistrationListener;->registrationDisconnected(Landroid/telephony/ims/ImsReasonInfo;)V
Lcom/android/ims/internal/IImsRegistrationListener;->registrationFeatureCapabilityChanged(I[I[I)V
@@ -598,6 +646,27 @@
Lcom/android/ims/internal/IImsUtListener;->utConfigurationQueryFailed(Lcom/android/ims/internal/IImsUt;ILandroid/telephony/ims/ImsReasonInfo;)V
Lcom/android/ims/internal/IImsUtListener;->utConfigurationUpdated(Lcom/android/ims/internal/IImsUt;I)V
Lcom/android/ims/internal/IImsUtListener;->utConfigurationUpdateFailed(Lcom/android/ims/internal/IImsUt;ILandroid/telephony/ims/ImsReasonInfo;)V
+Lcom/android/ims/internal/uce/common/CapInfo;->getCapTimestamp()J
+Lcom/android/ims/internal/uce/common/CapInfo;->isCdViaPresenceSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isFtHttpSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isFtSnFSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isFtSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isFtThumbSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isFullSnFGroupChatSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isGeoPullFtSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isGeoPullSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isGeoPushSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isImSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isIpVideoSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isIpVoiceSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isIsSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isRcsIpVideoCallSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isRcsIpVideoOnlyCallSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isRcsIpVoiceCallSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isSmSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isSpSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isVsDuringCSSupported()Z
+Lcom/android/ims/internal/uce/common/CapInfo;->isVsSupported()Z
Lcom/android/ims/internal/uce/common/StatusCode;->getStatusCode()I
Lcom/android/ims/internal/uce/common/UceLong;->getClientId()I
Lcom/android/ims/internal/uce/common/UceLong;-><init>()V
@@ -617,6 +686,24 @@
Lcom/android/ims/internal/uce/options/IOptionsService;->responseIncomingOptions(IIILjava/lang/String;Lcom/android/ims/internal/uce/options/OptionsCapInfo;Z)Lcom/android/ims/internal/uce/common/StatusCode;
Lcom/android/ims/internal/uce/options/IOptionsService;->setMyInfo(ILcom/android/ims/internal/uce/common/CapInfo;I)Lcom/android/ims/internal/uce/common/StatusCode;
Lcom/android/ims/internal/uce/options/IOptionsService$Stub;-><init>()V
+Lcom/android/ims/internal/uce/options/OptionsCapInfo;->getCapInfo()Lcom/android/ims/internal/uce/common/CapInfo;
+Lcom/android/ims/internal/uce/options/OptionsCapInfo;->getSdp()Ljava/lang/String;
+Lcom/android/ims/internal/uce/options/OptionsCapInfo;-><init>()V
+Lcom/android/ims/internal/uce/options/OptionsCapInfo;->setCapInfo(Lcom/android/ims/internal/uce/common/CapInfo;)V
+Lcom/android/ims/internal/uce/options/OptionsCapInfo;->setSdp(Ljava/lang/String;)V
+Lcom/android/ims/internal/uce/options/OptionsCmdId;-><init>()V
+Lcom/android/ims/internal/uce/options/OptionsCmdId;->setCmdId(I)V
+Lcom/android/ims/internal/uce/options/OptionsCmdStatus;-><init>()V
+Lcom/android/ims/internal/uce/options/OptionsCmdStatus;->setCapInfo(Lcom/android/ims/internal/uce/common/CapInfo;)V
+Lcom/android/ims/internal/uce/options/OptionsCmdStatus;->setCmdId(Lcom/android/ims/internal/uce/options/OptionsCmdId;)V
+Lcom/android/ims/internal/uce/options/OptionsCmdStatus;->setStatus(Lcom/android/ims/internal/uce/common/StatusCode;)V
+Lcom/android/ims/internal/uce/options/OptionsCmdStatus;->setUserData(I)V
+Lcom/android/ims/internal/uce/options/OptionsSipResponse;-><init>()V
+Lcom/android/ims/internal/uce/options/OptionsSipResponse;->setCmdId(Lcom/android/ims/internal/uce/options/OptionsCmdId;)V
+Lcom/android/ims/internal/uce/options/OptionsSipResponse;->setReasonPhrase(Ljava/lang/String;)V
+Lcom/android/ims/internal/uce/options/OptionsSipResponse;->setRequestId(I)V
+Lcom/android/ims/internal/uce/options/OptionsSipResponse;->setRetryAfter(I)V
+Lcom/android/ims/internal/uce/options/OptionsSipResponse;->setSipResponseCode(I)V
Lcom/android/ims/internal/uce/presence/IPresenceListener;->capInfoReceived(Ljava/lang/String;[Lcom/android/ims/internal/uce/presence/PresTupleInfo;)V
Lcom/android/ims/internal/uce/presence/IPresenceListener;->cmdStatus(Lcom/android/ims/internal/uce/presence/PresCmdStatus;)V
Lcom/android/ims/internal/uce/presence/IPresenceListener;->getVersionCb(Ljava/lang/String;)V
@@ -635,6 +722,12 @@
Lcom/android/ims/internal/uce/presence/IPresenceService;->removeListener(ILcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode;
Lcom/android/ims/internal/uce/presence/IPresenceService;->setNewFeatureTag(ILjava/lang/String;Lcom/android/ims/internal/uce/presence/PresServiceInfo;I)Lcom/android/ims/internal/uce/common/StatusCode;
Lcom/android/ims/internal/uce/presence/IPresenceService$Stub;-><init>()V
+Lcom/android/ims/internal/uce/presence/PresCapInfo;->getCapInfo()Lcom/android/ims/internal/uce/common/CapInfo;
+Lcom/android/ims/internal/uce/presence/PresCapInfo;->getContactUri()Ljava/lang/String;
+Lcom/android/ims/internal/uce/presence/PresServiceInfo;->getMediaType()I
+Lcom/android/ims/internal/uce/presence/PresServiceInfo;->getServiceDesc()Ljava/lang/String;
+Lcom/android/ims/internal/uce/presence/PresServiceInfo;->getServiceId()Ljava/lang/String;
+Lcom/android/ims/internal/uce/presence/PresServiceInfo;->getServiceVer()Ljava/lang/String;
Lcom/android/ims/internal/uce/presence/PresSipResponse;->getCmdId()Lcom/android/ims/internal/uce/presence/PresCmdId;
Lcom/android/ims/internal/uce/presence/PresSipResponse;->getReasonPhrase()Ljava/lang/String;
Lcom/android/ims/internal/uce/presence/PresSipResponse;->getRequestId()I
@@ -684,6 +777,9 @@
Lcom/android/internal/os/BatteryStatsImpl;->getPhoneSignalStrengthTime(IJI)J
Lcom/android/internal/os/BatteryStatsImpl;->getScreenBrightnessTime(IJI)J
Lcom/android/internal/os/BatteryStatsImpl;->getWifiOnTime(JI)J
+Lcom/android/internal/os/SomeArgs;->arg1:Ljava/lang/Object;
+Lcom/android/internal/os/SomeArgs;->arg2:Ljava/lang/Object;
+Lcom/android/internal/os/SomeArgs;->arg3:Ljava/lang/Object;
Lcom/android/internal/os/SomeArgs;->obtain()Lcom/android/internal/os/SomeArgs;
Lcom/android/internal/os/SomeArgs;->recycle()V
Lcom/android/internal/R$styleable;->NumberPicker:[I
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 3047cdb..289a4dd 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -959,8 +959,10 @@
* @hide
*/
static public boolean isHighEndGfx() {
- return !isLowRamDeviceStatic() &&
- !Resources.getSystem().getBoolean(com.android.internal.R.bool.config_avoidGfxAccel);
+ return !isLowRamDeviceStatic()
+ && !RoSystemProperties.CONFIG_AVOID_GFX_ACCEL
+ && !Resources.getSystem()
+ .getBoolean(com.android.internal.R.bool.config_avoidGfxAccel);
}
/**
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index f01eee4..1df724e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -30,12 +30,15 @@
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.app.backup.BackupAgent;
+import android.app.servertransaction.ActivityLifecycleItem;
import android.app.servertransaction.ActivityLifecycleItem.LifecycleState;
+import android.app.servertransaction.ActivityRelaunchItem;
import android.app.servertransaction.ActivityResultItem;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.PendingTransactionActions;
import android.app.servertransaction.PendingTransactionActions.StopInfo;
import android.app.servertransaction.TransactionExecutor;
+import android.app.servertransaction.TransactionExecutorHelper;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
@@ -520,6 +523,10 @@
return activityInfo.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS;
}
+ public boolean isVisibleFromServer() {
+ return activity != null && activity.mVisibleFromServer;
+ }
+
public String toString() {
ComponentName componentName = intent != null ? intent.getComponent() : null;
return "ActivityRecord{"
@@ -1797,6 +1804,7 @@
// message is handled.
transaction.recycle();
}
+ // TODO(lifecycler): Recycle locally scheduled transactions.
break;
}
Object obj = msg.obj;
@@ -2755,6 +2763,11 @@
}
}
+ @Override
+ TransactionExecutor getTransactionExecutor() {
+ return mTransactionExecutor;
+ }
+
void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}
@@ -4723,15 +4736,22 @@
return;
}
- // TODO(b/73747058): Investigate converting this to use transaction to relaunch.
- handleRelaunchActivityInner(r, 0 /* configChanges */, null /* pendingResults */,
- null /* pendingIntents */, null /* pendingActions */, prevState != ON_RESUME,
- r.overrideConfig, "handleRelaunchActivityLocally");
- // Restore back to the previous state before relaunch if needed.
- if (prevState != r.getLifecycleState()) {
- mTransactionExecutor.cycleToPath(r, prevState);
- }
+ // Initialize a relaunch request.
+ final MergedConfiguration mergedConfiguration = new MergedConfiguration(
+ r.createdConfig != null ? r.createdConfig : mConfiguration,
+ r.overrideConfig);
+ final ActivityRelaunchItem activityRelaunchItem = ActivityRelaunchItem.obtain(
+ null /* pendingResults */, null /* pendingIntents */, 0 /* configChanges */,
+ mergedConfiguration, r.mPreserveWindow);
+ // Make sure to match the existing lifecycle state in the end of the transaction.
+ final ActivityLifecycleItem lifecycleRequest =
+ TransactionExecutorHelper.getLifecycleRequestForCurrentState(r);
+ // Schedule the transaction.
+ final ClientTransaction transaction = ClientTransaction.obtain(this.mAppThread, r.token);
+ transaction.addCallback(activityRelaunchItem);
+ transaction.setLifecycleStateRequest(lifecycleRequest);
+ executeTransaction(transaction);
}
private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges,
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index f38c80c..a68136b 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2167,15 +2167,16 @@
@Override
public PersistableBundle getSuspendedPackageAppExtras(String packageName) {
try {
- return mPM.getPackageSuspendedAppExtras(packageName, mContext.getUserId());
+ return mPM.getSuspendedPackageAppExtras(packageName, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
@Override
- public PersistableBundle getSuspendedPackageAppExtras() {
- return getSuspendedPackageAppExtras(mContext.getOpPackageName());
+ public Bundle getSuspendedPackageAppExtras() {
+ final PersistableBundle extras = getSuspendedPackageAppExtras(mContext.getOpPackageName());
+ return extras != null ? new Bundle(extras.deepCopy()) : null;
}
@Override
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 961bca2..925080e 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -17,6 +17,7 @@
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.PendingTransactionActions;
+import android.app.servertransaction.TransactionExecutor;
import android.content.pm.ApplicationInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
@@ -43,6 +44,22 @@
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
+ /**
+ * Execute transaction immediately without scheduling it. This is used for local requests, so
+ * it will also recycle the transaction.
+ */
+ void executeTransaction(ClientTransaction transaction) {
+ transaction.preExecute(this);
+ getTransactionExecutor().execute(transaction);
+ transaction.recycle();
+ }
+
+ /**
+ * Get the {@link TransactionExecutor} that will be performing lifecycle transitions and
+ * callbacks for activities.
+ */
+ abstract TransactionExecutor getTransactionExecutor();
+
abstract void sendMessage(int what, Object obj);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 99efecd..e1a02fa 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -94,6 +94,7 @@
void registerUidObserver(in IUidObserver observer, int which, int cutpoint,
String callingPackage);
void unregisterUidObserver(in IUidObserver observer);
+ boolean isUidActive(int uid, String callingPackage);
// =============== End of transactions used on native side as well ============================
// Special low-level communication with activity manager.
@@ -322,12 +323,14 @@
/**
* Informs ActivityManagerService that the keyguard is showing.
*
- * @param showing True if the keyguard is showing, false otherwise.
+ * @param showingKeyguard True if the keyguard is showing, false otherwise.
+ * @param showingAod True if AOD is showing, false otherwise.
* @param secondaryDisplayShowing The displayId of the secondary display on which the keyguard
* is showing, or INVALID_DISPLAY if there is no such display. Only meaningful if
* showing is true.
*/
- void setLockScreenShown(boolean showing, int secondaryDisplayShowing);
+ void setLockScreenShown(boolean showingKeyguard, boolean showingAod,
+ int secondaryDisplayShowing);
boolean finishActivityAffinity(in IBinder token);
// This is not public because you need to be very careful in how you
// manage your activity to make sure it is always the uid you expect.
diff --git a/core/java/android/app/RemoteAction.java b/core/java/android/app/RemoteAction.java
index e7fe407..47741c0 100644
--- a/core/java/android/app/RemoteAction.java
+++ b/core/java/android/app/RemoteAction.java
@@ -18,14 +18,9 @@
import android.annotation.NonNull;
import android.graphics.drawable.Icon;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Messenger;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.RemoteException;
import android.text.TextUtils;
-import android.util.Log;
import java.io.PrintWriter;
@@ -42,6 +37,7 @@
private final CharSequence mContentDescription;
private final PendingIntent mActionIntent;
private boolean mEnabled;
+ private boolean mShouldShowIcon;
RemoteAction(Parcel in) {
mIcon = Icon.CREATOR.createFromParcel(in);
@@ -49,6 +45,7 @@
mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mActionIntent = PendingIntent.CREATOR.createFromParcel(in);
mEnabled = in.readBoolean();
+ mShouldShowIcon = in.readBoolean();
}
public RemoteAction(@NonNull Icon icon, @NonNull CharSequence title,
@@ -62,6 +59,7 @@
mContentDescription = contentDescription;
mActionIntent = intent;
mEnabled = true;
+ mShouldShowIcon = true;
}
/**
@@ -79,6 +77,20 @@
}
/**
+ * Sets whether the icon should be shown.
+ */
+ public void setShouldShowIcon(boolean shouldShowIcon) {
+ mShouldShowIcon = shouldShowIcon;
+ }
+
+ /**
+ * Return whether the icon should be shown.
+ */
+ public boolean shouldShowIcon() {
+ return mShouldShowIcon;
+ }
+
+ /**
* Return an icon representing the action.
*/
public @NonNull Icon getIcon() {
@@ -125,6 +137,7 @@
TextUtils.writeToParcel(mContentDescription, out, flags);
mActionIntent.writeToParcel(out, flags);
out.writeBoolean(mEnabled);
+ out.writeBoolean(mShouldShowIcon);
}
public void dump(String prefix, PrintWriter pw) {
@@ -134,6 +147,7 @@
pw.print(" contentDescription=" + mContentDescription);
pw.print(" icon=" + mIcon);
pw.print(" action=" + mActionIntent.getIntent());
+ pw.print(" shouldShowIcon=" + mShouldShowIcon);
pw.println();
}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 19240e2..465340f 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -57,10 +57,7 @@
import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.service.wallpaper.WallpaperService;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
@@ -444,6 +441,9 @@
synchronized (this) {
mCachedWallpaper = null;
mCachedWallpaperUserId = 0;
+ if (mDefaultWallpaper != null) {
+ mDefaultWallpaper.recycle();
+ }
mDefaultWallpaper = null;
}
}
@@ -915,9 +915,14 @@
/**
* Get the primary colors of a wallpaper.
*
- * <p>You can expect null if:
- * • Colors are still being processed by the system.
- * • A live wallpaper doesn't implement {@link WallpaperService.Engine#onComputeColors()}.
+ * <p>This method can return {@code null} when:
+ * <ul>
+ * <li>Colors are still being processed by the system.</li>
+ * <li>The user has chosen to use a live wallpaper: live wallpapers might not
+ * implement
+ * {@link android.service.wallpaper.WallpaperService.Engine#onComputeColors()
+ * WallpaperService.Engine#onComputeColors()}.</li>
+ * </ul>
*
* @param which Wallpaper type. Must be either {@link #FLAG_SYSTEM} or
* {@link #FLAG_LOCK}.
@@ -929,7 +934,7 @@
}
/**
- * Get the primary colors of a wallpaper
+ * Get the primary colors of the wallpaper configured in the given user.
* @param which wallpaper type. Must be either {@link #FLAG_SYSTEM} or
* {@link #FLAG_LOCK}
* @param userId Owner of the wallpaper.
@@ -1559,11 +1564,13 @@
* Specify extra padding that the wallpaper should have outside of the display.
* That is, the given padding supplies additional pixels the wallpaper should extend
* outside of the display itself.
+ *
+ * <p>This method requires the caller to hold the permission
+ * {@link android.Manifest.permission#SET_WALLPAPER_HINTS}.
+ *
* @param padding The number of pixels the wallpaper should extend beyond the display,
* on its left, top, right, and bottom sides.
- * @hide
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.SET_WALLPAPER_HINTS)
public void setDisplayPadding(Rect padding) {
try {
@@ -1600,11 +1607,11 @@
}
/**
- * Clear the wallpaper.
+ * Reset all wallpaper to the factory default.
*
- * @hide
+ * <p>This method requires the caller to hold the permission
+ * {@link android.Manifest.permission#SET_WALLPAPER}.
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public void clearWallpaper() {
clearWallpaper(FLAG_LOCK, mContext.getUserId());
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3015398..436947f 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3742,7 +3742,7 @@
public static final int KEYGUARD_DISABLE_TRUST_AGENTS = 1 << 4;
/**
- * Disable fingerprint sensor on keyguard secure screens (e.g. PIN/Pattern/Password).
+ * Disable fingerprint authentication on keyguard secure screens (e.g. PIN/Pattern/Password).
*/
public static final int KEYGUARD_DISABLE_FINGERPRINT = 1 << 5;
@@ -3752,6 +3752,25 @@
public static final int KEYGUARD_DISABLE_REMOTE_INPUT = 1 << 6;
/**
+ * Disable face authentication on keyguard secure screens (e.g. PIN/Pattern/Password).
+ */
+ public static final int KEYGUARD_DISABLE_FACE = 1 << 7;
+
+ /**
+ * Disable iris authentication on keyguard secure screens (e.g. PIN/Pattern/Password).
+ */
+ public static final int KEYGUARD_DISABLE_IRIS = 1 << 8;
+
+ /**
+ * Disable all biometric authentication on keyguard secure screens (e.g. PIN/Pattern/Password).
+ */
+ public static final int KEYGUARD_DISABLE_BIOMETRICS =
+ DevicePolicyManager.KEYGUARD_DISABLE_FACE
+ | DevicePolicyManager.KEYGUARD_DISABLE_IRIS
+ | DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
+
+
+ /**
* Disable all current and future keyguard customizations.
*/
public static final int KEYGUARD_DISABLE_FEATURES_ALL = 0x7fffffff;
diff --git a/core/java/android/app/servertransaction/TransactionExecutorHelper.java b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
index 7e66fd7..01b13a2 100644
--- a/core/java/android/app/servertransaction/TransactionExecutorHelper.java
+++ b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
@@ -26,7 +26,7 @@
import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE;
import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED;
-import android.app.ActivityThread;
+import android.app.ActivityThread.ActivityClientRecord;
import android.util.IntArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -124,7 +124,7 @@
* {@link ActivityLifecycleItem#UNDEFINED} if there is not path.
*/
@VisibleForTesting
- public int getClosestPreExecutionState(ActivityThread.ActivityClientRecord r,
+ public int getClosestPreExecutionState(ActivityClientRecord r,
int postExecutionState) {
switch (postExecutionState) {
case UNDEFINED:
@@ -147,7 +147,7 @@
* were provided or there is not path.
*/
@VisibleForTesting
- public int getClosestOfStates(ActivityThread.ActivityClientRecord r, int[] finalStates) {
+ public int getClosestOfStates(ActivityClientRecord r, int[] finalStates) {
if (finalStates == null || finalStates.length == 0) {
return UNDEFINED;
}
@@ -168,6 +168,27 @@
return closestState;
}
+ /** Get the lifecycle state request to match the current state in the end of a transaction. */
+ public static ActivityLifecycleItem getLifecycleRequestForCurrentState(ActivityClientRecord r) {
+ final int prevState = r.getLifecycleState();
+ final ActivityLifecycleItem lifecycleItem;
+ switch (prevState) {
+ // TODO(lifecycler): Extend to support all possible states.
+ case ON_PAUSE:
+ lifecycleItem = PauseActivityItem.obtain();
+ break;
+ case ON_STOP:
+ lifecycleItem = StopActivityItem.obtain(r.isVisibleFromServer(),
+ 0 /* configChanges */);
+ break;
+ default:
+ lifecycleItem = ResumeActivityItem.obtain(false /* isForward */);
+ break;
+ }
+
+ return lifecycleItem;
+ }
+
/**
* Check if there is a destruction involved in the path. We want to avoid a lifecycle sequence
* that involves destruction and recreation if there is another path.
diff --git a/core/java/android/app/usage/EventStats.java b/core/java/android/app/usage/EventStats.java
new file mode 100644
index 0000000..b799de9
--- /dev/null
+++ b/core/java/android/app/usage/EventStats.java
@@ -0,0 +1,182 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package android.app.usage;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Contains usage statistics for an event type for a specific
+ * time range.
+ */
+public final class EventStats implements Parcelable {
+
+ /**
+ * {@hide}
+ */
+ public int mEventType;
+
+ /**
+ * {@hide}
+ */
+ public long mBeginTimeStamp;
+
+ /**
+ * {@hide}
+ */
+ public long mEndTimeStamp;
+
+ /**
+ * Last time used by the user with an explicit action (notification, activity launch).
+ * {@hide}
+ */
+ public long mLastTimeUsed;
+
+ /**
+ * {@hide}
+ */
+ public long mTotalTime;
+
+ /**
+ * {@hide}
+ */
+ public int mCount;
+
+ /**
+ * {@hide}
+ */
+ public EventStats() {
+ }
+
+ public EventStats(EventStats stats) {
+ mEventType = stats.mEventType;
+ mBeginTimeStamp = stats.mBeginTimeStamp;
+ mEndTimeStamp = stats.mEndTimeStamp;
+ mLastTimeUsed = stats.mLastTimeUsed;
+ mTotalTime = stats.mTotalTime;
+ mCount = stats.mCount;
+ }
+
+ /**
+ * Return the type of event this is usage for. May be one of the event
+ * constants in {@link UsageEvents.Event}.
+ */
+ public int getEventType() {
+ return mEventType;
+ }
+
+ /**
+ * Get the beginning of the time range this {@link android.app.usage.EventStats} represents,
+ * measured in milliseconds since the epoch.
+ * <p/>
+ * See {@link System#currentTimeMillis()}.
+ */
+ public long getFirstTimeStamp() {
+ return mBeginTimeStamp;
+ }
+
+ /**
+ * Get the end of the time range this {@link android.app.usage.EventStats} represents,
+ * measured in milliseconds since the epoch.
+ * <p/>
+ * See {@link System#currentTimeMillis()}.
+ */
+ public long getLastTimeStamp() {
+ return mEndTimeStamp;
+ }
+
+ /**
+ * Get the last time this event was used, measured in milliseconds since the epoch.
+ * <p/>
+ * See {@link System#currentTimeMillis()}.
+ */
+ public long getLastTimeUsed() {
+ return mLastTimeUsed;
+ }
+
+ /**
+ * Return the number of times that this event occurred over the interval.
+ */
+ public int getCount() {
+ return mCount;
+ }
+
+ /**
+ * Get the total time this event was active, measured in milliseconds.
+ */
+ public long getTotalTime() {
+ return mTotalTime;
+ }
+
+ /**
+ * Add the statistics from the right {@link EventStats} to the left. The event type for
+ * both {@link UsageStats} objects must be the same.
+ * @param right The {@link EventStats} object to merge into this one.
+ * @throws java.lang.IllegalArgumentException if the event types of the two
+ * {@link UsageStats} objects are different.
+ */
+ public void add(EventStats right) {
+ if (mEventType != right.mEventType) {
+ throw new IllegalArgumentException("Can't merge EventStats for event #"
+ + mEventType + " with EventStats for event #" + right.mEventType);
+ }
+
+ // We use the mBeginTimeStamp due to a bug where UsageStats files can overlap with
+ // regards to their mEndTimeStamp.
+ if (right.mBeginTimeStamp > mBeginTimeStamp) {
+ mLastTimeUsed = Math.max(mLastTimeUsed, right.mLastTimeUsed);
+ }
+ mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp);
+ mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
+ mTotalTime += right.mTotalTime;
+ mCount += right.mCount;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mEventType);
+ dest.writeLong(mBeginTimeStamp);
+ dest.writeLong(mEndTimeStamp);
+ dest.writeLong(mLastTimeUsed);
+ dest.writeLong(mTotalTime);
+ dest.writeInt(mCount);
+ }
+
+ public static final Creator<EventStats> CREATOR = new Creator<EventStats>() {
+ @Override
+ public EventStats createFromParcel(Parcel in) {
+ EventStats stats = new EventStats();
+ stats.mEventType = in.readInt();
+ stats.mBeginTimeStamp = in.readLong();
+ stats.mEndTimeStamp = in.readLong();
+ stats.mLastTimeUsed = in.readLong();
+ stats.mTotalTime = in.readLong();
+ stats.mCount = in.readInt();
+ return stats;
+ }
+
+ @Override
+ public EventStats[] newArray(int size) {
+ return new EventStats[size];
+ }
+ };
+}
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index d52bd37..00d8711 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -32,6 +32,8 @@
String callingPackage);
ParceledListSlice queryConfigurationStats(int bucketType, long beginTime, long endTime,
String callingPackage);
+ ParceledListSlice queryEventStats(int bucketType, long beginTime, long endTime,
+ String callingPackage);
UsageEvents queryEvents(long beginTime, long endTime, String callingPackage);
UsageEvents queryEventsForPackage(long beginTime, long endTime, String callingPackage);
void setAppInactive(String packageName, boolean inactive, int userId);
diff --git a/core/java/android/app/usage/TimeSparseArray.java b/core/java/android/app/usage/TimeSparseArray.java
index 5764fa8..9ef88e4 100644
--- a/core/java/android/app/usage/TimeSparseArray.java
+++ b/core/java/android/app/usage/TimeSparseArray.java
@@ -81,12 +81,17 @@
@Override
public void put(long key, E value) {
final long origKey = key;
- while (indexOfKey(key) >= 0) {
- key++;
- }
- if (origKey != key) {
- Slog.w(TAG, "Value " + value + " supposed to be inserted at " + origKey
- + " displaced to " + key);
+ int keyIndex = indexOfKey(key);
+ if (keyIndex >= 0) {
+ final long sz = size();
+ while (keyIndex < sz && keyAt(keyIndex) == key) {
+ key++;
+ keyIndex++;
+ }
+ if (key >= origKey + 10) {
+ Slog.w(TAG, "Value " + value + " supposed to be inserted at " + origKey
+ + " displaced to " + key);
+ }
}
super.put(key, value);
}
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index b354e81..a665652 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -139,6 +139,19 @@
@SystemApi
public static final int SLICE_PINNED = 14;
+ /**
+ * An event type denoting that the screen has gone in to an interactive state (turned
+ * on for full user interaction, not ambient display or other non-interactive state).
+ */
+ public static final int SCREEN_INTERACTIVE = 15;
+
+ /**
+ * An event type denoting that the screen has gone in to a non-interactive state
+ * (completely turned off or turned on only in a non-interactive state like ambient
+ * display).
+ */
+ public static final int SCREEN_NON_INTERACTIVE = 16;
+
/** @hide */
public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 4744147..6feb527 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -301,6 +301,44 @@
}
/**
+ * Gets aggregated event stats for the given time range, aggregated by the specified interval.
+ * <p>The returned list will contain a {@link EventStats} object for each event type that
+ * is being aggregated and has data for an interval that is a subset of the time range given.
+ *
+ * <p>The current event types that will be aggregated here are:</p>
+ * <ul>
+ * <li>{@link UsageEvents.Event#SCREEN_INTERACTIVE}</li>
+ * <li>{@link UsageEvents.Event#SCREEN_NON_INTERACTIVE}</li>
+ * </ul>
+ *
+ * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p>
+ *
+ * @param intervalType The time interval by which the stats are aggregated.
+ * @param beginTime The inclusive beginning of the range of stats to include in the results.
+ * @param endTime The exclusive end of the range of stats to include in the results.
+ * @return A list of {@link EventStats}
+ *
+ * @see #INTERVAL_DAILY
+ * @see #INTERVAL_WEEKLY
+ * @see #INTERVAL_MONTHLY
+ * @see #INTERVAL_YEARLY
+ * @see #INTERVAL_BEST
+ */
+ public List<EventStats> queryEventStats(int intervalType, long beginTime, long endTime) {
+ try {
+ @SuppressWarnings("unchecked")
+ ParceledListSlice<EventStats> slice = mService.queryEventStats(intervalType, beginTime,
+ endTime, mContext.getOpPackageName());
+ if (slice != null) {
+ return slice.getList();
+ }
+ } catch (RemoteException e) {
+ // fallthrough and return the empty list.
+ }
+ return Collections.emptyList();
+ }
+
+ /**
* Query for events in the given time range. Events are only kept by the system for a few
* days.
* <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p>
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index ce32278..02f0ded 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1814,6 +1814,17 @@
public static final String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";
/**
+ * Intent extra: A {@link Bundle} of extras for a package being suspended. Will be sent with
+ * {@link #ACTION_MY_PACKAGE_SUSPENDED}.
+ *
+ * @see #ACTION_MY_PACKAGE_SUSPENDED
+ * @see #ACTION_MY_PACKAGE_UNSUSPENDED
+ * @see PackageManager#isPackageSuspended()
+ * @see PackageManager#getSuspendedPackageAppExtras()
+ */
+ public static final String EXTRA_SUSPENDED_PACKAGE_EXTRAS = "android.intent.extra.SUSPENDED_PACKAGE_EXTRAS";
+
+ /**
* Intent extra: An app split name.
* <p>
* Type: String
@@ -2237,6 +2248,43 @@
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_PACKAGES_UNSUSPENDED = "android.intent.action.PACKAGES_UNSUSPENDED";
+
+ /**
+ * Broadcast Action: Sent to a package that has been suspended by the system. This is sent
+ * whenever a package is put into a suspended state or any of it's app extras change while
+ * in the suspended state.
+ * <p> Optionally includes the following extras:
+ * <ul>
+ * <li> {@link #EXTRA_SUSPENDED_PACKAGE_EXTRAS} which is a {@link Bundle} which will contain
+ * useful information for the app being suspended.
+ * </ul>
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system. <em>This will be delivered to {@link BroadcastReceiver} components declared in
+ * the manifest.</em>
+ *
+ * @see #ACTION_MY_PACKAGE_UNSUSPENDED
+ * @see #EXTRA_SUSPENDED_PACKAGE_EXTRAS
+ * @see PackageManager#isPackageSuspended()
+ * @see PackageManager#getSuspendedPackageAppExtras()
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_MY_PACKAGE_SUSPENDED = "android.intent.action.MY_PACKAGE_SUSPENDED";
+
+ /**
+ * Broadcast Action: Sent to a package that has been unsuspended.
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system. <em>This will be delivered to {@link BroadcastReceiver} components declared in
+ * the manifest.</em>
+ *
+ * @see #ACTION_MY_PACKAGE_SUSPENDED
+ * @see #EXTRA_SUSPENDED_PACKAGE_EXTRAS
+ * @see PackageManager#isPackageSuspended()
+ * @see PackageManager#getSuspendedPackageAppExtras()
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_MY_PACKAGE_UNSUSPENDED = "android.intent.action.MY_PACKAGE_UNSUSPENDED";
+
/**
* Broadcast Action: A user ID has been removed from the system. The user
* ID number is stored in the extra data under {@link #EXTRA_UID}.
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index d43d80f..277738b 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -278,7 +278,7 @@
boolean isPackageSuspendedForUser(String packageName, int userId);
- PersistableBundle getPackageSuspendedAppExtras(String pacakgeName, int userId);
+ PersistableBundle getSuspendedPackageAppExtras(String packageName, int userId);
void setSuspendedPackageAppExtras(String packageName, in PersistableBundle appExtras,
int userId);
@@ -619,6 +619,8 @@
in String[] packageNames, int userId);
void revokeDefaultPermissionsFromDisabledTelephonyDataServices(
in String[] packageNames, int userId);
+ void grantDefaultPermissionsToActiveLuiApp(in String packageName, int userId);
+ void revokeDefaultPermissionsFromLuiApps(in String[] packageNames, int userId);
boolean isPermissionRevokedByPolicy(String permission, String packageName, int userId);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 314eb98..491f0af 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5513,7 +5513,7 @@
* Puts the package in a suspended state, where attempts at starting activities are denied.
*
* <p>It doesn't remove the data or the actual package file. The application's notifications
- * will be hidden, any of the it's started activities will be stopped and it will not be able to
+ * will be hidden, any of its started activities will be stopped and it will not be able to
* show toasts or dialogs or ring the device. When the user tries to launch a suspended app, a
* system dialog with the given {@code dialogMessage} will be shown instead.</p>
*
@@ -5577,11 +5577,26 @@
}
/**
- * Apps can query this to know if they have been suspended.
+ * Apps can query this to know if they have been suspended. A system app with the permission
+ * {@code android.permission.SUSPEND_APPS} can put any app on the device into a suspended state.
+ *
+ * <p>While in this state, the application's notifications will be hidden, any of its started
+ * activities will be stopped and it will not be able to show toasts or dialogs or ring the
+ * device. When the user tries to launch a suspended app, the system will, instead, show a
+ * dialog to the user informing them that they cannot use this app while it is suspended.
+ *
+ * <p>When an app is put into this state, the broadcast action
+ * {@link Intent#ACTION_MY_PACKAGE_SUSPENDED} will be delivered to any of its broadcast
+ * receivers that included this action in their intent-filters, <em>including manifest
+ * receivers.</em> Similarly, a broadcast action {@link Intent#ACTION_MY_PACKAGE_UNSUSPENDED}
+ * is delivered when a previously suspended app is taken out of this state.
+ * </p>
*
* @return {@code true} if the calling package has been suspended, {@code false} otherwise.
*
* @see #getSuspendedPackageAppExtras()
+ * @see Intent#ACTION_MY_PACKAGE_SUSPENDED
+ * @see Intent#ACTION_MY_PACKAGE_UNSUSPENDED
*/
public boolean isPackageSuspended() {
throw new UnsupportedOperationException("isPackageSuspended not implemented");
@@ -5602,7 +5617,7 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.SUSPEND_APPS)
- public PersistableBundle getSuspendedPackageAppExtras(String packageName) {
+ public @Nullable PersistableBundle getSuspendedPackageAppExtras(String packageName) {
throw new UnsupportedOperationException("getSuspendedPackageAppExtras not implemented");
}
@@ -5631,15 +5646,17 @@
* Returns any extra information supplied as {@code appExtras} to the system when the calling
* app was suspended.
*
- * <p> Note: This just returns whatever {@link PersistableBundle} was passed to the system via
- * {@code setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle,
- * String)} when suspending the package, <em> which might be {@code null}. </em></p>
+ * <p>Note: If no extras were supplied to the system, this method will return {@code null}, even
+ * when the calling app has been suspended.</p>
*
- * @return A {@link PersistableBundle} containing the extras for the app, or {@code null} if the
+ * @return A {@link Bundle} containing the extras for the app, or {@code null} if the
* package is not currently suspended.
+ *
* @see #isPackageSuspended()
+ * @see Intent#ACTION_MY_PACKAGE_UNSUSPENDED
+ * @see Intent#ACTION_MY_PACKAGE_SUSPENDED
*/
- public @Nullable PersistableBundle getSuspendedPackageAppExtras() {
+ public @Nullable Bundle getSuspendedPackageAppExtras() {
throw new UnsupportedOperationException("getSuspendedPackageAppExtras not implemented");
}
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index 56cba79..c6c676f 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -31,7 +31,7 @@
import java.util.regex.Pattern;
/**
- * This is a convience class that helps build SQL queries to be sent to
+ * This is a convenience class that helps build SQL queries to be sent to
* {@link SQLiteDatabase} objects.
*/
public class SQLiteQueryBuilder
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
new file mode 100644
index 0000000..a037289
--- /dev/null
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics;
+
+
+/**
+ * Interface containing all of the biometric modality agnostic constants.
+ * @hide
+ */
+public interface BiometricConstants {
+ //
+ // Error messages from biometric hardware during initilization, enrollment, authentication or
+ // removal.
+ //
+
+ /**
+ * The hardware is unavailable. Try again later.
+ */
+ int BIOMETRIC_ERROR_HW_UNAVAILABLE = 1;
+
+ /**
+ * Error state returned when the sensor was unable to process the current image.
+ */
+ int BIOMETRIC_ERROR_UNABLE_TO_PROCESS = 2;
+
+ /**
+ * Error state returned when the current request has been running too long. This is intended to
+ * prevent programs from waiting for the biometric sensor indefinitely. The timeout is platform
+ * and sensor-specific, but is generally on the order of 30 seconds.
+ */
+ int BIOMETRIC_ERROR_TIMEOUT = 3;
+
+ /**
+ * Error state returned for operations like enrollment; the operation cannot be completed
+ * because there's not enough storage remaining to complete the operation.
+ */
+ int BIOMETRIC_ERROR_NO_SPACE = 4;
+
+ /**
+ * The operation was canceled because the biometric sensor is unavailable. For example, this may
+ * happen when the user is switched, the device is locked or another pending operation prevents
+ * or disables it.
+ */
+ int BIOMETRIC_ERROR_CANCELED = 5;
+
+ /**
+ * The {@link BiometricManager#remove} call failed. Typically this will happen when the provided
+ * biometric id was incorrect.
+ *
+ * @hide
+ */
+ int BIOMETRIC_ERROR_UNABLE_TO_REMOVE = 6;
+
+ /**
+ * The operation was canceled because the API is locked out due to too many attempts.
+ * This occurs after 5 failed attempts, and lasts for 30 seconds.
+ */
+ int BIOMETRIC_ERROR_LOCKOUT = 7;
+
+ /**
+ * Hardware vendors may extend this list if there are conditions that do not fall under one of
+ * the above categories. Vendors are responsible for providing error strings for these errors.
+ * These messages are typically reserved for internal operations such as enrollment, but may be
+ * used to express vendor errors not otherwise covered. Applications are expected to show the
+ * error message string if they happen, but are advised not to rely on the message id since they
+ * will be device and vendor-specific
+ */
+ int BIOMETRIC_ERROR_VENDOR = 8;
+
+ /**
+ * The operation was canceled because BIOMETRIC_ERROR_LOCKOUT occurred too many times.
+ * Biometric authentication is disabled until the user unlocks with strong authentication
+ * (PIN/Pattern/Password)
+ */
+ int BIOMETRIC_ERROR_LOCKOUT_PERMANENT = 9;
+
+ /**
+ * The user canceled the operation. Upon receiving this, applications should use alternate
+ * authentication (e.g. a password). The application should also provide the means to return to
+ * biometric authentication, such as a "use <biometric>" button.
+ */
+ int BIOMETRIC_ERROR_USER_CANCELED = 10;
+
+ /**
+ * The user does not have any biometrics enrolled.
+ */
+ int BIOMETRIC_ERROR_NO_BIOMETRICS = 11;
+
+ /**
+ * The device does not have a biometric sensor.
+ */
+ int BIOMETRIC_ERROR_HW_NOT_PRESENT = 12;
+
+ /**
+ * @hide
+ */
+ int BIOMETRIC_ERROR_VENDOR_BASE = 1000;
+
+ //
+ // Image acquisition messages.
+ //
+
+ /**
+ * The image acquired was good.
+ */
+ int BIOMETRIC_ACQUIRED_GOOD = 0;
+
+ /**
+ * Only a partial biometric image was detected. During enrollment, the user should be informed
+ * on what needs to happen to resolve this problem, e.g. "press firmly on sensor." (for
+ * fingerprint)
+ */
+ int BIOMETRIC_ACQUIRED_PARTIAL = 1;
+
+ /**
+ * The biometric image was too noisy to process due to a detected condition or a possibly dirty
+ * sensor (See {@link #BIOMETRIC_ACQUIRED_IMAGER_DIRTY}).
+ */
+ int BIOMETRIC_ACQUIRED_INSUFFICIENT = 2;
+
+ /**
+ * The biometric image was too noisy due to suspected or detected dirt on the sensor. For
+ * example, it's reasonable return this after multiple {@link #BIOMETRIC_ACQUIRED_INSUFFICIENT}
+ * or actual detection of dirt on the sensor (stuck pixels, swaths, etc.). The user is expected
+ * to take action to clean the sensor when this is returned.
+ */
+ int BIOMETRIC_ACQUIRED_IMAGER_DIRTY = 3;
+
+ /**
+ * The biometric image was unreadable due to lack of motion.
+ */
+ int BIOMETRIC_ACQUIRED_TOO_SLOW = 4;
+
+ /**
+ * The biometric image was incomplete due to quick motion. For example, this could also happen
+ * if the user moved during acquisition. The user should be asked to repeat the operation more
+ * slowly.
+ */
+ int BIOMETRIC_ACQUIRED_TOO_FAST = 5;
+
+ /**
+ * Hardware vendors may extend this list if there are conditions that do not fall under one of
+ * the above categories. Vendors are responsible for providing error strings for these errors.
+ * @hide
+ */
+ int BIOMETRIC_ACQUIRED_VENDOR = 6;
+ /**
+ * @hide
+ */
+ int BIOMETRICT_ACQUIRED_VENDOR_BASE = 1000;
+}
diff --git a/core/java/android/hardware/fingerprint/FingerprintDialog.java b/core/java/android/hardware/biometrics/BiometricDialog.java
similarity index 72%
rename from core/java/android/hardware/fingerprint/FingerprintDialog.java
rename to core/java/android/hardware/biometrics/BiometricDialog.java
index 49835963..dd848a3 100644
--- a/core/java/android/hardware/fingerprint/FingerprintDialog.java
+++ b/core/java/android/hardware/biometrics/BiometricDialog.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package android.hardware.fingerprint;
+package android.hardware.biometrics;
-import static android.Manifest.permission.USE_FINGERPRINT;
+import static android.Manifest.permission.USE_BIOMETRIC;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
@@ -24,10 +24,7 @@
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
-import android.hardware.biometrics.BiometricAuthenticator;
-import android.hardware.biometrics.BiometricFingerprintConstants;
-import android.hardware.biometrics.CryptoObject;
-import android.hardware.fingerprint.IFingerprintDialogReceiver;
+import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.text.TextUtils;
@@ -39,9 +36,9 @@
import javax.crypto.Mac;
/**
- * A class that manages a system-provided fingerprint dialog.
+ * A class that manages a system-provided biometric dialog.
*/
-public class FingerprintDialog implements BiometricAuthenticator, BiometricFingerprintConstants {
+public class BiometricDialog implements BiometricAuthenticator, BiometricConstants {
/**
* @hide
@@ -71,7 +68,7 @@
* after this amount of time.
* @hide
*/
- public static final int HIDE_DIALOG_DELAY = 3000; // ms
+ public static final int HIDE_DIALOG_DELAY = 2000; // ms
/**
* @hide
*/
@@ -97,18 +94,21 @@
}
/**
- * A builder that collects arguments, to be shown on the system-provided fingerprint dialog.
+ * A builder that collects arguments to be shown on the system-provided biometric dialog.
**/
public static class Builder {
- private final Bundle bundle;
- private ButtonInfo positiveButtonInfo;
- private ButtonInfo negativeButtonInfo;
+ private final Bundle mBundle;
+ private ButtonInfo mPositiveButtonInfo;
+ private ButtonInfo mNegativeButtonInfo;
+ private Context mContext;
/**
- * Creates a builder for a fingerprint dialog.
+ * Creates a builder for a biometric dialog.
+ * @param context
*/
- public Builder() {
- bundle = new Bundle();
+ public Builder(Context context) {
+ mBundle = new Bundle();
+ mContext = context;
}
/**
@@ -117,7 +117,7 @@
* @return
*/
public Builder setTitle(@NonNull CharSequence title) {
- bundle.putCharSequence(KEY_TITLE, title);
+ mBundle.putCharSequence(KEY_TITLE, title);
return this;
}
@@ -127,7 +127,7 @@
* @return
*/
public Builder setSubtitle(@NonNull CharSequence subtitle) {
- bundle.putCharSequence(KEY_SUBTITLE, subtitle);
+ mBundle.putCharSequence(KEY_SUBTITLE, subtitle);
return this;
}
@@ -137,7 +137,7 @@
* @return
*/
public Builder setDescription(@NonNull CharSequence description) {
- bundle.putCharSequence(KEY_DESCRIPTION, description);
+ mBundle.putCharSequence(KEY_DESCRIPTION, description);
return this;
}
@@ -160,13 +160,15 @@
if (listener == null) {
throw new IllegalArgumentException("Listener must not be null");
}
- bundle.putCharSequence(KEY_POSITIVE_TEXT, text);
- positiveButtonInfo = new ButtonInfo(executor, listener);
+ mBundle.putCharSequence(KEY_POSITIVE_TEXT, text);
+ mPositiveButtonInfo = new ButtonInfo(executor, listener);
return this;
}
/**
- * Required: Set the text for the negative button.
+ * Required: Set the text for the negative button. This would typically be used as a
+ * "Cancel" button, but may be also used to show an alternative method for authentication,
+ * such as screen that asks for a backup password.
* @param text
* @return
*/
@@ -182,27 +184,26 @@
if (listener == null) {
throw new IllegalArgumentException("Listener must not be null");
}
- bundle.putCharSequence(KEY_NEGATIVE_TEXT, text);
- negativeButtonInfo = new ButtonInfo(executor, listener);
+ mBundle.putCharSequence(KEY_NEGATIVE_TEXT, text);
+ mNegativeButtonInfo = new ButtonInfo(executor, listener);
return this;
}
/**
- * Creates a {@link FingerprintDialog} with the arguments supplied to this builder.
- * @param context
- * @return a {@link FingerprintDialog}
+ * Creates a {@link BiometricDialog}.
+ * @return a {@link BiometricDialog}
* @throws IllegalArgumentException if any of the required fields are not set.
*/
- public FingerprintDialog build(Context context) {
- final CharSequence title = bundle.getCharSequence(KEY_TITLE);
- final CharSequence negative = bundle.getCharSequence(KEY_NEGATIVE_TEXT);
+ public BiometricDialog build() {
+ final CharSequence title = mBundle.getCharSequence(KEY_TITLE);
+ final CharSequence negative = mBundle.getCharSequence(KEY_NEGATIVE_TEXT);
if (TextUtils.isEmpty(title)) {
throw new IllegalArgumentException("Title must be set and non-empty");
} else if (TextUtils.isEmpty(negative)) {
throw new IllegalArgumentException("Negative text must be set and non-empty");
}
- return new FingerprintDialog(context, bundle, positiveButtonInfo, negativeButtonInfo);
+ return new BiometricDialog(mContext, mBundle, mPositiveButtonInfo, mNegativeButtonInfo);
}
}
@@ -212,7 +213,7 @@
private ButtonInfo mPositiveButtonInfo;
private ButtonInfo mNegativeButtonInfo;
- IFingerprintDialogReceiver mDialogReceiver = new IFingerprintDialogReceiver.Stub() {
+ IBiometricDialogReceiver mDialogReceiver = new IBiometricDialogReceiver.Stub() {
@Override
public void onDialogDismissed(int reason) {
// Check the reason and invoke OnClickListener(s) if necessary
@@ -228,7 +229,7 @@
}
};
- private FingerprintDialog(Context context, Bundle bundle,
+ private BiometricDialog(Context context, Bundle bundle,
ButtonInfo positiveButtonInfo, ButtonInfo negativeButtonInfo) {
mBundle = bundle;
mPositiveButtonInfo = positiveButtonInfo;
@@ -238,8 +239,8 @@
}
/**
- * 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 BiometricDialog. Currently the framework
+ * supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
*/
public static final class CryptoObject extends android.hardware.biometrics.CryptoObject {
public CryptoObject(@NonNull Signature signature) {
@@ -280,9 +281,8 @@
}
/**
- * Container for callback data from {@link #authenticate(
- * CancellationSignal, Executor, AuthenticationCallback)} and
- * {@link #authenticate(CryptoObject, CancellationSignal, Executor,
+ * Container for callback data from {@link #authenticate( CancellationSignal, Executor,
+ * AuthenticationCallback)} and {@link #authenticate(CryptoObject, CancellationSignal, Executor,
* AuthenticationCallback)}
*/
public static class AuthenticationResult extends BiometricAuthenticator.AuthenticationResult {
@@ -299,8 +299,8 @@
}
/**
* Obtain the crypto object associated with this transaction
- * @return crypto object provided to {@link #authenticate(
- * CryptoObject, CancellationSignal, Executor, AuthenticationCallback)}
+ * @return crypto object provided to {@link #authenticate( CryptoObject, CancellationSignal,
+ * Executor, AuthenticationCallback)}
*/
public CryptoObject getCryptoObject() {
return (CryptoObject) super.getCryptoObject();
@@ -308,12 +308,12 @@
}
/**
- * Callback structure provided to {@link FingerprintDialog#authenticate(CancellationSignal,
- * Executor, AuthenticationCallback)} or {@link FingerprintDialog#authenticate(CryptoObject,
+ * Callback structure provided to {@link BiometricDialog#authenticate(CancellationSignal,
+ * Executor, AuthenticationCallback)} or {@link BiometricDialog#authenticate(CryptoObject,
* CancellationSignal, Executor, AuthenticationCallback)}. Users must provide an implementation
* of this for listening to authentication events.
*/
- public static abstract class AuthenticationCallback extends
+ public abstract static class AuthenticationCallback extends
BiometricAuthenticator.AuthenticationCallback {
/**
* Called when an unrecoverable error has been encountered and the operation is complete.
@@ -366,7 +366,6 @@
}
}
-
/**
* @param crypto Object associated with the call
* @param cancel An object that can be used to cancel authentication
@@ -379,7 +378,7 @@
@NonNull CancellationSignal cancel,
@NonNull @CallbackExecutor Executor executor,
@NonNull BiometricAuthenticator.AuthenticationCallback callback) {
- if (!(callback instanceof FingerprintDialog.AuthenticationCallback)) {
+ if (!(callback instanceof BiometricDialog.AuthenticationCallback)) {
throw new IllegalArgumentException("Callback cannot be casted");
}
authenticate(crypto, cancel, executor, (AuthenticationCallback) callback);
@@ -396,30 +395,26 @@
public void authenticate(@NonNull CancellationSignal cancel,
@NonNull @CallbackExecutor Executor executor,
@NonNull BiometricAuthenticator.AuthenticationCallback callback) {
- if (!(callback instanceof FingerprintDialog.AuthenticationCallback)) {
+ if (!(callback instanceof BiometricDialog.AuthenticationCallback)) {
throw new IllegalArgumentException("Callback cannot be casted");
}
authenticate(cancel, executor, (AuthenticationCallback) callback);
}
-
/**
- * This call warms up the fingerprint hardware, displays a system-provided dialog,
- * and starts scanning for a fingerprint. It terminates when
- * {@link AuthenticationCallback#onAuthenticationError(int,
- * CharSequence)} is called, when
- * {@link AuthenticationCallback#onAuthenticationSucceeded(
- * AuthenticationResult)}, or when the user dismisses the system-provided dialog, at which point
- * the crypto object becomes invalid. This operation can be canceled by using the provided
- * cancel object. The application will receive authentication errors through
- * {@link AuthenticationCallback}, and button events through the
- * corresponding callback set in {@link Builder#setNegativeButton(CharSequence,
- * Executor, DialogInterface.OnClickListener)}. It is safe to reuse the
- * {@link FingerprintDialog} object, and calling {@link FingerprintDialog#authenticate(
- * CancellationSignal, Executor, AuthenticationCallback)} while an
- * existing authentication attempt is occurring will stop the previous client and start a
- * new authentication. The interrupted client will receive a cancelled notification through
- * {@link AuthenticationCallback#onAuthenticationError(int,
+ * This call warms up the fingerprint hardware, displays a system-provided dialog, and starts
+ * scanning for a fingerprint. It terminates when {@link
+ * AuthenticationCallback#onAuthenticationError(int, CharSequence)} is called, when {@link
+ * AuthenticationCallback#onAuthenticationSucceeded( AuthenticationResult)}, or when the user
+ * dismisses the system-provided dialog, at which point the crypto object becomes invalid. This
+ * operation can be canceled by using the provided cancel object. The application will receive
+ * authentication errors through {@link AuthenticationCallback}, and button events through the
+ * corresponding callback set in {@link Builder#setNegativeButton(CharSequence, Executor,
+ * DialogInterface.OnClickListener)}. It is safe to reuse the {@link BiometricDialog} object,
+ * and calling {@link BiometricDialog#authenticate( CancellationSignal, Executor,
+ * AuthenticationCallback)} while an existing authentication attempt is occurring will stop the
+ * previous client and start a new authentication. The interrupted client will receive a
+ * cancelled notification through {@link AuthenticationCallback#onAuthenticationError(int,
* CharSequence)}.
*
* @throws IllegalArgumentException If any of the arguments are null
@@ -429,7 +424,7 @@
* @param executor An executor to handle callback events
* @param callback An object to receive authentication events
*/
- @RequiresPermission(USE_FINGERPRINT)
+ @RequiresPermission(USE_BIOMETRIC)
public void authenticate(@NonNull CryptoObject crypto,
@NonNull CancellationSignal cancel,
@NonNull @CallbackExecutor Executor executor,
@@ -442,23 +437,19 @@
}
/**
- * This call warms up the fingerprint hardware, displays a system-provided dialog,
- * and starts scanning for a fingerprint. It terminates when
- * {@link AuthenticationCallback#onAuthenticationError(int,
- * CharSequence)} is called, when
- * {@link AuthenticationCallback#onAuthenticationSucceeded(
- * AuthenticationResult)} is called, or when the user dismisses the system-provided dialog.
- * This operation can be canceled by using the provided cancel object. The application will
- * receive authentication errors through {@link AuthenticationCallback},
- * and button events through the corresponding callback set in
- * {@link Builder#setNegativeButton(CharSequence, Executor, DialogInterface.OnClickListener)}.
- * It is safe to reuse the {@link FingerprintDialog} object, and calling
- * {@link FingerprintDialog#authenticate(CancellationSignal, Executor,
- * AuthenticationCallback)} while an existing authentication attempt is
- * occurring will stop the previous client and start a new authentication. The interrupted
- * client will receive a cancelled notification through
- * {@link AuthenticationCallback#onAuthenticationError(int,
- * CharSequence)}.
+ * This call warms up the fingerprint hardware, displays a system-provided dialog, and starts
+ * scanning for a fingerprint. It terminates when {@link
+ * AuthenticationCallback#onAuthenticationError(int, CharSequence)} is called, when {@link
+ * AuthenticationCallback#onAuthenticationSucceeded( AuthenticationResult)} is called, or when
+ * the user dismisses the system-provided dialog. This operation can be canceled by using the
+ * provided cancel object. The application will receive authentication errors through {@link
+ * AuthenticationCallback}, and button events through the corresponding callback set in {@link
+ * Builder#setNegativeButton(CharSequence, Executor, DialogInterface.OnClickListener)}. It is
+ * safe to reuse the {@link BiometricDialog} object, and calling {@link
+ * BiometricDialog#authenticate(CancellationSignal, Executor, AuthenticationCallback)} while
+ * an existing authentication attempt is occurring will stop the previous client and start a new
+ * authentication. The interrupted client will receive a cancelled notification through {@link
+ * AuthenticationCallback#onAuthenticationError(int, CharSequence)}.
*
* @throws IllegalArgumentException If any of the arguments are null
*
@@ -466,7 +457,7 @@
* @param executor An executor to handle callback events
* @param callback An object to receive authentication events
*/
- @RequiresPermission(USE_FINGERPRINT)
+ @RequiresPermission(USE_BIOMETRIC)
public void authenticate(@NonNull CancellationSignal cancel,
@NonNull @CallbackExecutor Executor executor,
@NonNull AuthenticationCallback callback) {
@@ -479,13 +470,16 @@
private boolean handlePreAuthenticationErrors(AuthenticationCallback callback,
Executor executor) {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
- sendError(FINGERPRINT_ERROR_HW_NOT_PRESENT, callback, executor);
+ sendError(BiometricDialog.BIOMETRIC_ERROR_HW_NOT_PRESENT, callback,
+ executor);
return true;
} else if (!mFingerprintManager.isHardwareDetected()) {
- sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, callback, executor);
+ sendError(BiometricDialog.BIOMETRIC_ERROR_HW_UNAVAILABLE, callback,
+ executor);
return true;
} else if (!mFingerprintManager.hasEnrolledFingerprints()) {
- sendError(FINGERPRINT_ERROR_NO_FINGERPRINTS, callback, executor);
+ sendError(BiometricDialog.BIOMETRIC_ERROR_NO_BIOMETRICS, callback,
+ executor);
return true;
}
return false;
diff --git a/core/java/android/hardware/fingerprint/IFingerprintDialogReceiver.aidl b/core/java/android/hardware/biometrics/IBiometricDialogReceiver.aidl
similarity index 76%
rename from core/java/android/hardware/fingerprint/IFingerprintDialogReceiver.aidl
rename to core/java/android/hardware/biometrics/IBiometricDialogReceiver.aidl
index 13e7974..e528aa7 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintDialogReceiver.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricDialogReceiver.aidl
@@ -13,16 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.hardware.fingerprint;
+package android.hardware.biometrics;
-import android.hardware.fingerprint.Fingerprint;
import android.os.Bundle;
import android.os.UserHandle;
/**
- * Communication channel from the FingerprintDialog (SysUI) back to AuthenticationClient.
+ * Communication channel from the BiometricDialog (SysUI) back to AuthenticationClient.
* @hide
*/
-oneway interface IFingerprintDialogReceiver {
+oneway interface IBiometricDialogReceiver {
void onDialogDismissed(int reason);
}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 390b83f..e6aaab1 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -3392,6 +3392,21 @@
public static final Key<Integer> LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE =
new Key<Integer>("android.logicalMultiCamera.sensorSyncType", int.class);
+ /**
+ * <p>List of distortion correction modes for {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} that are
+ * supported by this camera device.</p>
+ * <p>No device is required to support this API; such devices will always list only 'OFF'.
+ * All devices that support this API will list both FAST and HIGH_QUALITY.</p>
+ * <p><b>Range of valid values:</b><br>
+ * Any value listed in {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode}</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CaptureRequest#DISTORTION_CORRECTION_MODE
+ */
+ @PublicKey
+ public static final Key<int[]> DISTORTION_CORRECTION_AVAILABLE_MODES =
+ new Key<int[]>("android.distortionCorrection.availableModes", int[].class);
+
/*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
* End generated code
*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 7669c01..7467c3a 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -2730,6 +2730,31 @@
public static final int TONEMAP_PRESET_CURVE_REC709 = 1;
//
+ // Enumeration values for CaptureRequest#DISTORTION_CORRECTION_MODE
+ //
+
+ /**
+ * <p>No distortion correction is applied.</p>
+ * @see CaptureRequest#DISTORTION_CORRECTION_MODE
+ */
+ public static final int DISTORTION_CORRECTION_MODE_OFF = 0;
+
+ /**
+ * <p>Lens distortion correction is applied without reducing frame rate
+ * relative to sensor output. It may be the same as OFF if distortion correction would
+ * reduce frame rate relative to sensor.</p>
+ * @see CaptureRequest#DISTORTION_CORRECTION_MODE
+ */
+ public static final int DISTORTION_CORRECTION_MODE_FAST = 1;
+
+ /**
+ * <p>High-quality distortion correction is applied, at the cost of
+ * possibly reduced frame rate relative to sensor output.</p>
+ * @see CaptureRequest#DISTORTION_CORRECTION_MODE
+ */
+ public static final int DISTORTION_CORRECTION_MODE_HIGH_QUALITY = 2;
+
+ //
// Enumeration values for CaptureResult#CONTROL_AE_STATE
//
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index b0cbec7..d36785a 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -3167,6 +3167,49 @@
public static final Key<Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR =
new Key<Float>("android.reprocess.effectiveExposureFactor", float.class);
+ /**
+ * <p>Mode of operation for the lens distortion correction block.</p>
+ * <p>The lens distortion correction block attempts to improve image quality by fixing
+ * radial, tangential, or other geometric aberrations in the camera device's optics. If
+ * available, the {@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion} field documents the lens's distortion parameters.</p>
+ * <p>OFF means no distortion correction is done.</p>
+ * <p>FAST/HIGH_QUALITY both mean camera device determined distortion correction will be
+ * applied. HIGH_QUALITY mode indicates that the camera device will use the highest-quality
+ * correction algorithms, even if it slows down capture rate. FAST means the camera device
+ * will not slow down capture rate when applying correction. FAST may be the same as OFF if
+ * any correction at all would slow down capture rate. Every output stream will have a
+ * similar amount of enhancement applied.</p>
+ * <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not
+ * applied to any RAW output. Metadata coordinates such as face rectangles or metering
+ * regions are also not affected by correction.</p>
+ * <p>Applications enabling distortion correction need to pay extra attention when converting
+ * image coordinates between corrected output buffers and the sensor array. For example, if
+ * the app supports tap-to-focus and enables correction, it then has to apply the distortion
+ * model described in {@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion} to the image buffer tap coordinates to properly
+ * calculate the tap position on the sensor active array to be used with
+ * {@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}. The same applies in reverse to detected face rectangles if
+ * they need to be drawn on top of the corrected output buffers.</p>
+ * <p><b>Possible values:</b>
+ * <ul>
+ * <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li>
+ * <li>{@link #DISTORTION_CORRECTION_MODE_FAST FAST}</li>
+ * <li>{@link #DISTORTION_CORRECTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
+ * </ul></p>
+ * <p><b>Available values for this device:</b><br>
+ * {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CaptureRequest#CONTROL_AF_REGIONS
+ * @see CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES
+ * @see CameraCharacteristics#LENS_DISTORTION
+ * @see #DISTORTION_CORRECTION_MODE_OFF
+ * @see #DISTORTION_CORRECTION_MODE_FAST
+ * @see #DISTORTION_CORRECTION_MODE_HIGH_QUALITY
+ */
+ @PublicKey
+ public static final Key<Integer> DISTORTION_CORRECTION_MODE =
+ new Key<Integer>("android.distortionCorrection.mode", int.class);
+
/*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
* End generated code
*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 6331942..bb82260 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -4450,6 +4450,49 @@
public static final Key<Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR =
new Key<Float>("android.reprocess.effectiveExposureFactor", float.class);
+ /**
+ * <p>Mode of operation for the lens distortion correction block.</p>
+ * <p>The lens distortion correction block attempts to improve image quality by fixing
+ * radial, tangential, or other geometric aberrations in the camera device's optics. If
+ * available, the {@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion} field documents the lens's distortion parameters.</p>
+ * <p>OFF means no distortion correction is done.</p>
+ * <p>FAST/HIGH_QUALITY both mean camera device determined distortion correction will be
+ * applied. HIGH_QUALITY mode indicates that the camera device will use the highest-quality
+ * correction algorithms, even if it slows down capture rate. FAST means the camera device
+ * will not slow down capture rate when applying correction. FAST may be the same as OFF if
+ * any correction at all would slow down capture rate. Every output stream will have a
+ * similar amount of enhancement applied.</p>
+ * <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not
+ * applied to any RAW output. Metadata coordinates such as face rectangles or metering
+ * regions are also not affected by correction.</p>
+ * <p>Applications enabling distortion correction need to pay extra attention when converting
+ * image coordinates between corrected output buffers and the sensor array. For example, if
+ * the app supports tap-to-focus and enables correction, it then has to apply the distortion
+ * model described in {@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion} to the image buffer tap coordinates to properly
+ * calculate the tap position on the sensor active array to be used with
+ * {@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}. The same applies in reverse to detected face rectangles if
+ * they need to be drawn on top of the corrected output buffers.</p>
+ * <p><b>Possible values:</b>
+ * <ul>
+ * <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li>
+ * <li>{@link #DISTORTION_CORRECTION_MODE_FAST FAST}</li>
+ * <li>{@link #DISTORTION_CORRECTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
+ * </ul></p>
+ * <p><b>Available values for this device:</b><br>
+ * {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CaptureRequest#CONTROL_AF_REGIONS
+ * @see CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES
+ * @see CameraCharacteristics#LENS_DISTORTION
+ * @see #DISTORTION_CORRECTION_MODE_OFF
+ * @see #DISTORTION_CORRECTION_MODE_FAST
+ * @see #DISTORTION_CORRECTION_MODE_HIGH_QUALITY
+ */
+ @PublicKey
+ public static final Key<Integer> DISTORTION_CORRECTION_MODE =
+ new Key<Integer>("android.distortionCorrection.mode", int.class);
+
/*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
* End generated code
*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 8048099c..5e28570 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.MANAGE_FINGERPRINT;
+import static android.Manifest.permission.USE_BIOMETRIC;
import static android.Manifest.permission.USE_FINGERPRINT;
import android.annotation.CallbackExecutor;
@@ -30,7 +31,9 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.biometrics.BiometricAuthenticator;
+import android.hardware.biometrics.BiometricDialog;
import android.hardware.biometrics.BiometricFingerprintConstants;
+import android.hardware.biometrics.IBiometricDialogReceiver;
import android.os.Binder;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -54,10 +57,10 @@
/**
* A class that coordinates access to the fingerprint hardware.
- * @deprecated See {@link FingerprintDialog} which shows a system-provided dialog upon starting
- * authentication. In a world where devices may have in-display fingerprint sensors, it's much
- * more realistic to have a system-provided authentication dialog since the in-display sensor
- * location may vary by vendor/device.
+ * @deprecated See {@link BiometricDialog} which shows a system-provided dialog upon starting
+ * authentication. In a world where devices may have different types of biometric authentication,
+ * it's much more realistic to have a system-provided authentication dialog since the method may
+ * vary by vendor/device.
*/
@Deprecated
@SystemService(Context.FINGERPRINT_SERVICE)
@@ -108,7 +111,7 @@
/**
* A wrapper class for the crypto objects supported by FingerprintManager. Currently the
* framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
- * @deprecated See {@link android.hardware.fingerprint.FingerprintDialog.CryptoObject}
+ * @deprecated See {@link android.hardware.biometrics.BiometricDialog.CryptoObject}
*/
@Deprecated
public static final class CryptoObject extends android.hardware.biometrics.CryptoObject {
@@ -152,7 +155,7 @@
/**
* Container for callback data from {@link FingerprintManager#authenticate(CryptoObject,
* CancellationSignal, int, AuthenticationCallback, Handler)}.
- * @deprecated See {@link android.hardware.fingerprint.FingerprintDialog.AuthenticationResult}
+ * @deprecated See {@link android.hardware.biometrics.BiometricDialog.AuthenticationResult}
*/
@Deprecated
public static class AuthenticationResult {
@@ -201,7 +204,7 @@
* FingerprintManager#authenticate(CryptoObject, CancellationSignal,
* int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to
* fingerprint events.
- * @deprecated See {@link android.hardware.fingerprint.FingerprintDialog.AuthenticationCallback}
+ * @deprecated See {@link android.hardware.biometrics.BiometricDialog.AuthenticationCallback}
*/
@Deprecated
public static abstract class AuthenticationCallback
@@ -375,13 +378,13 @@
* by <a href="{@docRoot}training/articles/keystore.html">Android Keystore
* facility</a>.
* @throws IllegalStateException if the crypto primitive is not initialized.
- * @deprecated See {@link FingerprintDialog#authenticate(CancellationSignal, Executor,
- * FingerprintDialog.AuthenticationCallback)} and {@link FingerprintDialog#authenticate(
- * FingerprintDialog.CryptoObject, CancellationSignal, Executor,
- * FingerprintDialog.AuthenticationCallback)}
+ * @deprecated See {@link BiometricDialog#authenticate(CancellationSignal, Executor,
+ * BiometricDialog.AuthenticationCallback)} and {@link BiometricDialog#authenticate(
+ * BiometricDialog.CryptoObject, CancellationSignal, Executor,
+ * BiometricDialog.AuthenticationCallback)}
*/
@Deprecated
- @RequiresPermission(USE_FINGERPRINT)
+ @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) {
authenticate(crypto, cancel, flags, callback, handler, mContext.getUserId());
@@ -405,7 +408,7 @@
* @param userId the user ID that the fingerprint hardware will authenticate for.
* @hide
*/
- @RequiresPermission(USE_FINGERPRINT)
+ @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) {
if (callback == null) {
@@ -441,7 +444,7 @@
/**
* Per-user version, see {@link FingerprintManager#authenticate(CryptoObject,
- * CancellationSignal, Bundle, Executor, IFingerprintDialogReceiver, AuthenticationCallback)}
+ * CancellationSignal, Bundle, Executor, IBiometricDialogReceiver, AuthenticationCallback)}
* @param userId the user ID that the fingerprint hardware will authenticate for.
*/
private void authenticate(int userId,
@@ -449,7 +452,7 @@
@NonNull CancellationSignal cancel,
@NonNull Bundle bundle,
@NonNull @CallbackExecutor Executor executor,
- @NonNull IFingerprintDialogReceiver receiver,
+ @NonNull IBiometricDialogReceiver receiver,
@NonNull BiometricAuthenticator.AuthenticationCallback callback) {
mCryptoObject = crypto;
if (cancel.isCanceled()) {
@@ -477,8 +480,8 @@
}
/**
- * Private method, see {@link FingerprintDialog#authenticate(CancellationSignal, Executor,
- * AuthenticationCallback)}
+ * Private method, see {@link BiometricDialog#authenticate(CancellationSignal, Executor,
+ * BiometricDialog.AuthenticationCallback)}
* @param cancel
* @param executor
* @param callback
@@ -488,7 +491,7 @@
@NonNull CancellationSignal cancel,
@NonNull Bundle bundle,
@NonNull @CallbackExecutor Executor executor,
- @NonNull IFingerprintDialogReceiver receiver,
+ @NonNull IBiometricDialogReceiver receiver,
@NonNull BiometricAuthenticator.AuthenticationCallback callback) {
if (cancel == null) {
throw new IllegalArgumentException("Must supply a cancellation signal");
@@ -509,8 +512,8 @@
}
/**
- * Private method, see {@link FingerprintDialog#authenticate(CryptoObject, CancellationSignal,
- * Executor, AuthenticationCallback)}
+ * Private method, see {@link BiometricDialog#authenticate(BiometricDialog.CryptoObject,
+ * CancellationSignal, Executor, BiometricDialog.AuthenticationCallback)}
* @param crypto
* @param cancel
* @param executor
@@ -521,7 +524,7 @@
@NonNull CancellationSignal cancel,
@NonNull Bundle bundle,
@NonNull @CallbackExecutor Executor executor,
- @NonNull IFingerprintDialogReceiver receiver,
+ @NonNull IBiometricDialogReceiver receiver,
@NonNull BiometricAuthenticator.AuthenticationCallback callback) {
if (crypto == null) {
throw new IllegalArgumentException("Must supply a crypto object");
@@ -740,8 +743,8 @@
* Determine if there is at least one fingerprint enrolled.
*
* @return true if at least one fingerprint is enrolled, false otherwise
- * @deprecated See {@link FingerprintDialog} and
- * {@link FingerprintDialog#FINGERPRINT_ERROR_NO_FINGERPRINTS}
+ * @deprecated See {@link BiometricDialog} and
+ * {@link FingerprintManager#FINGERPRINT_ERROR_NO_FINGERPRINTS}
*/
@Deprecated
@RequiresPermission(USE_FINGERPRINT)
@@ -774,8 +777,8 @@
* Determine if fingerprint hardware is present and functional.
*
* @return true if hardware is present and functional, false otherwise.
- * @deprecated See {@link FingerprintDialog} and
- * {@link FingerprintDialog#FINGERPRINT_ERROR_HW_UNAVAILABLE}
+ * @deprecated See {@link BiometricDialog} and
+ * {@link FingerprintManager#FINGERPRINT_ERROR_HW_UNAVAILABLE}
*/
@Deprecated
@RequiresPermission(USE_FINGERPRINT)
@@ -1155,9 +1158,14 @@
@Override // binder call
public void onError(long deviceId, int error, int vendorCode) {
if (mExecutor != null) {
- mExecutor.execute(() -> {
- sendErrorResult(deviceId, error, vendorCode);
- });
+ // BiometricDialog case, post a delayed runnable on the FingerprintManager handler
+ // that sends the error message after FingerprintDialog.HIDE_DIALOG_DELAY to send
+ // the error to the application.
+ mHandler.postDelayed(() -> {
+ mExecutor.execute(() -> {
+ sendErrorResult(deviceId, error, vendorCode);
+ });
+ }, BiometricDialog.HIDE_DIALOG_DELAY);
} else {
mHandler.obtainMessage(MSG_ERROR, error, vendorCode, deviceId).sendToTarget();
}
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index f1502e4..78d01e5 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -16,8 +16,8 @@
package android.hardware.fingerprint;
import android.os.Bundle;
+import android.hardware.biometrics.IBiometricDialogReceiver;
import android.hardware.fingerprint.IFingerprintClientActiveCallback;
-import android.hardware.fingerprint.IFingerprintDialogReceiver;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
import android.hardware.fingerprint.Fingerprint;
@@ -31,7 +31,7 @@
// Authenticate the given sessionId with a fingerprint
void authenticate(IBinder token, long sessionId, int userId,
IFingerprintServiceReceiver receiver, int flags, String opPackageName,
- in Bundle bundle, IFingerprintDialogReceiver dialogReceiver);
+ in Bundle bundle, IBiometricDialogReceiver dialogReceiver);
// Cancel authentication for the given sessionId
void cancelAuthentication(IBinder token, String opPackageName);
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index ef58f94..ff5714b 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -17,7 +17,6 @@
package android.net;
import android.annotation.IntDef;
-import android.annotation.SystemApi;
import android.net.ConnectivityManager.NetworkCallback;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index f528d63..6ebb102 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1585,6 +1585,7 @@
public static final int STATE2_CAMERA_FLAG = 1<<21;
public static final int STATE2_BLUETOOTH_SCAN_FLAG = 1 << 20;
public static final int STATE2_CELLULAR_HIGH_TX_POWER_FLAG = 1 << 19;
+ public static final int STATE2_USB_DATA_LINK_FLAG = 1 << 18;
public static final int MOST_INTERESTING_STATES2 =
STATE2_POWER_SAVE_FLAG | STATE2_WIFI_ON_FLAG | STATE2_DEVICE_IDLE_MASK
@@ -2363,8 +2364,7 @@
SCREEN_BRIGHTNESS_NAMES, SCREEN_BRIGHTNESS_SHORT_NAMES),
};
- public static final BitDescription[] HISTORY_STATE2_DESCRIPTIONS
- = new BitDescription[] {
+ public static final BitDescription[] HISTORY_STATE2_DESCRIPTIONS = new BitDescription[] {
new BitDescription(HistoryItem.STATE2_POWER_SAVE_FLAG, "power_save", "ps"),
new BitDescription(HistoryItem.STATE2_VIDEO_ON_FLAG, "video", "v"),
new BitDescription(HistoryItem.STATE2_WIFI_RUNNING_FLAG, "wifi_running", "Ww"),
@@ -2375,6 +2375,7 @@
new String[] { "off", "light", "full", "???" },
new String[] { "off", "light", "full", "???" }),
new BitDescription(HistoryItem.STATE2_CHARGING_FLAG, "charging", "ch"),
+ new BitDescription(HistoryItem.STATE2_USB_DATA_LINK_FLAG, "usb_data", "Ud"),
new BitDescription(HistoryItem.STATE2_PHONE_IN_CALL_FLAG, "phone_in_call", "Pcl"),
new BitDescription(HistoryItem.STATE2_BLUETOOTH_ON_FLAG, "bluetooth", "b"),
new BitDescription(HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK,
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index e22c65f..8378a82 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -295,8 +295,10 @@
/**
* The current lowest supported value of app target SDK. Applications targeting
- * lower values will fail to install and run. Its possible values are defined
- * in {@link Build.VERSION_CODES}.
+ * lower values may not function on devices running this SDK version. Its possible
+ * values are defined in {@link Build.VERSION_CODES}.
+ *
+ * @hide
*/
public static final int MIN_SUPPORTED_TARGET_SDK_INT = SystemProperties.getInt(
"ro.build.version.min_supported_target_sdk", 0);
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 62bb385..e3c4870 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -2803,8 +2803,8 @@
Class<?> parcelableClass = Class.forName(name, false /* initialize */,
parcelableClassLoader);
if (!Parcelable.class.isAssignableFrom(parcelableClass)) {
- throw new BadParcelableException("Parcelable protocol requires that the "
- + "class implements Parcelable");
+ throw new BadParcelableException("Parcelable protocol requires subclassing "
+ + "from Parcelable on class " + name);
}
Field f = parcelableClass.getField("CREATOR");
if ((f.getModifiers() & Modifier.STATIC) == 0) {
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index d3877ca..5c99f6c 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -269,22 +269,7 @@
return (mountFlags & MOUNT_FLAG_VISIBLE) != 0;
}
- public boolean isVisibleForRead(int userId) {
- if (type == TYPE_PUBLIC) {
- if (isPrimary() && mountUserId != userId) {
- // Primary physical is only visible to single user
- return false;
- } else {
- return isVisible();
- }
- } else if (type == TYPE_EMULATED) {
- return isVisible();
- } else {
- return false;
- }
- }
-
- public boolean isVisibleForWrite(int userId) {
+ public boolean isVisibleForUser(int userId) {
if (type == TYPE_PUBLIC && mountUserId == userId) {
return isVisible();
} else if (type == TYPE_EMULATED) {
@@ -294,6 +279,14 @@
}
}
+ public boolean isVisibleForRead(int userId) {
+ return isVisibleForUser(userId);
+ }
+
+ public boolean isVisibleForWrite(int userId) {
+ return isVisibleForUser(userId);
+ }
+
public File getPath() {
return (path != null) ? new File(path) : null;
}
@@ -409,9 +402,9 @@
* Build an intent to browse the contents of this volume. Only valid for
* {@link #TYPE_EMULATED} or {@link #TYPE_PUBLIC}.
*/
- public Intent buildBrowseIntent() {
+ public @Nullable Intent buildBrowseIntent() {
final Uri uri;
- if (type == VolumeInfo.TYPE_PUBLIC) {
+ if (type == VolumeInfo.TYPE_PUBLIC && mountUserId == UserHandle.myUserId()) {
uri = DocumentsContract.buildRootUri(DOCUMENT_AUTHORITY, fsUuid);
} else if (type == VolumeInfo.TYPE_EMULATED && isPrimary()) {
uri = DocumentsContract.buildRootUri(DOCUMENT_AUTHORITY,
diff --git a/core/java/android/provider/BlockedNumberContract.java b/core/java/android/provider/BlockedNumberContract.java
index 8aef012..67c6fb9 100644
--- a/core/java/android/provider/BlockedNumberContract.java
+++ b/core/java/android/provider/BlockedNumberContract.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
+import android.telecom.Log;
/**
* <p>
@@ -261,9 +262,16 @@
*/
@WorkerThread
public static boolean isBlocked(Context context, String phoneNumber) {
- final Bundle res = context.getContentResolver().call(
- AUTHORITY_URI, METHOD_IS_BLOCKED, phoneNumber, null);
- return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);
+ try {
+ final Bundle res = context.getContentResolver().call(
+ AUTHORITY_URI, METHOD_IS_BLOCKED, phoneNumber, null);
+ return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);
+ } catch (NullPointerException | IllegalArgumentException ex) {
+ // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+ // either of these happen.
+ Log.w(null, "isBlocked: provider not ready.");
+ return false;
+ }
}
/**
@@ -297,9 +305,16 @@
* @return {@code true} if the current user can block numbers.
*/
public static boolean canCurrentUserBlockNumbers(Context context) {
- final Bundle res = context.getContentResolver().call(
- AUTHORITY_URI, METHOD_CAN_CURRENT_USER_BLOCK_NUMBERS, null, null);
- return res != null && res.getBoolean(RES_CAN_BLOCK_NUMBERS, false);
+ try {
+ final Bundle res = context.getContentResolver().call(
+ AUTHORITY_URI, METHOD_CAN_CURRENT_USER_BLOCK_NUMBERS, null, null);
+ return res != null && res.getBoolean(RES_CAN_BLOCK_NUMBERS, false);
+ } catch (NullPointerException | IllegalArgumentException ex) {
+ // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+ // either of these happen.
+ Log.w(null, "canCurrentUserBlockNumbers: provider not ready.");
+ return false;
+ }
}
/**
@@ -368,8 +383,14 @@
* the provider unless {@link #endBlockSuppression(Context)} is called.
*/
public static void notifyEmergencyContact(Context context) {
- context.getContentResolver().call(
- AUTHORITY_URI, METHOD_NOTIFY_EMERGENCY_CONTACT, null, null);
+ try {
+ context.getContentResolver().call(
+ AUTHORITY_URI, METHOD_NOTIFY_EMERGENCY_CONTACT, null, null);
+ } catch (NullPointerException | IllegalArgumentException ex) {
+ // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+ // either of these happen.
+ Log.w(null, "notifyEmergencyContact: provider not ready.");
+ }
}
/**
@@ -394,9 +415,16 @@
*/
public static boolean shouldSystemBlockNumber(Context context, String phoneNumber,
Bundle extras) {
- final Bundle res = context.getContentResolver().call(
- AUTHORITY_URI, METHOD_SHOULD_SYSTEM_BLOCK_NUMBER, phoneNumber, extras);
- return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);
+ try {
+ final Bundle res = context.getContentResolver().call(
+ AUTHORITY_URI, METHOD_SHOULD_SYSTEM_BLOCK_NUMBER, phoneNumber, extras);
+ return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);
+ } catch (NullPointerException | IllegalArgumentException ex) {
+ // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+ // either of these happen.
+ Log.w(null, "shouldSystemBlockNumber: provider not ready.");
+ return false;
+ }
}
/**
@@ -416,9 +444,16 @@
* @return {@code true} if should show emergency call notification. {@code false} otherwise.
*/
public static boolean shouldShowEmergencyCallNotification(Context context) {
- final Bundle res = context.getContentResolver().call(
- AUTHORITY_URI, METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION, null, null);
- return res != null && res.getBoolean(RES_SHOW_EMERGENCY_CALL_NOTIFICATION, false);
+ try {
+ final Bundle res = context.getContentResolver().call(
+ AUTHORITY_URI, METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION, null, null);
+ return res != null && res.getBoolean(RES_SHOW_EMERGENCY_CALL_NOTIFICATION, false);
+ } catch (NullPointerException | IllegalArgumentException ex) {
+ // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+ // either of these happen.
+ Log.w(null, "shouldShowEmergencyCallNotification: provider not ready.");
+ return false;
+ }
}
/**
@@ -436,9 +471,16 @@
public static boolean getEnhancedBlockSetting(Context context, String key) {
Bundle extras = new Bundle();
extras.putString(EXTRA_ENHANCED_SETTING_KEY, key);
- final Bundle res = context.getContentResolver().call(
- AUTHORITY_URI, METHOD_GET_ENHANCED_BLOCK_SETTING, null, extras);
- return res != null && res.getBoolean(RES_ENHANCED_SETTING_IS_ENABLED, false);
+ try {
+ final Bundle res = context.getContentResolver().call(
+ AUTHORITY_URI, METHOD_GET_ENHANCED_BLOCK_SETTING, null, extras);
+ return res != null && res.getBoolean(RES_ENHANCED_SETTING_IS_ENABLED, false);
+ } catch (NullPointerException | IllegalArgumentException ex) {
+ // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+ // either of these happen.
+ Log.w(null, "getEnhancedBlockSetting: provider not ready.");
+ return false;
+ }
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 9ecae8c..70f343e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7801,6 +7801,14 @@
"low_power_warning_acknowledged";
/**
+ * 0 (default) Auto battery saver suggestion has not been suppressed. 1) it has been
+ * suppressed.
+ * @hide
+ */
+ public static final String SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION =
+ "suppress_auto_battery_saver_suggestion";
+
+ /**
* This are the settings to be backed up.
*
* NOTE: Settings are backed up and restored in the order they appear
diff --git a/core/java/android/se/omapi/Channel.java b/core/java/android/se/omapi/Channel.java
index 65ce67f..c8efede 100644
--- a/core/java/android/se/omapi/Channel.java
+++ b/core/java/android/se/omapi/Channel.java
@@ -47,7 +47,8 @@
private final SEService mService;
private final Object mLock = new Object();
- Channel(SEService service, Session session, ISecureElementChannel channel) {
+ Channel(@NonNull SEService service, @NonNull Session session,
+ @NonNull ISecureElementChannel channel) {
if (service == null || session == null || channel == null) {
throw new IllegalArgumentException("Parameters cannot be null");
}
@@ -158,7 +159,7 @@
* @throws SecurityException if the command is filtered by the security policy.
* @throws NullPointerException if command is NULL.
*/
- public @NonNull byte[] transmit(byte[] command) throws IOException {
+ public @NonNull byte[] transmit(@NonNull byte[] command) throws IOException {
if (!mService.isConnected()) {
throw new IllegalStateException("service not connected to system");
}
diff --git a/core/java/android/se/omapi/ISecureElementListener.aidl b/core/java/android/se/omapi/ISecureElementListener.aidl
index e0c6e04..e9dd181 100644
--- a/core/java/android/se/omapi/ISecureElementListener.aidl
+++ b/core/java/android/se/omapi/ISecureElementListener.aidl
@@ -24,8 +24,4 @@
* @hide
*/
interface ISecureElementListener {
- /**
- * Called by the framework when the service is connected.
- */
- void serviceConnected();
}
diff --git a/core/java/android/se/omapi/Reader.java b/core/java/android/se/omapi/Reader.java
index 3dec976..9be3da6 100644
--- a/core/java/android/se/omapi/Reader.java
+++ b/core/java/android/se/omapi/Reader.java
@@ -46,7 +46,7 @@
private final Object mLock = new Object();
- Reader(SEService service, String name, ISecureElementReader reader) {
+ Reader(@NonNull SEService service, @NonNull String name, @NonNull ISecureElementReader reader) {
if (reader == null || service == null || name == null) {
throw new IllegalArgumentException("Parameters cannot be null");
}
diff --git a/core/java/android/se/omapi/SEService.java b/core/java/android/se/omapi/SEService.java
index d59e86a..311dc4c 100644
--- a/core/java/android/se/omapi/SEService.java
+++ b/core/java/android/se/omapi/SEService.java
@@ -62,17 +62,32 @@
/**
* Interface to send call-backs to the application when the service is connected.
*/
- public abstract static class SecureElementListener extends ISecureElementListener.Stub {
+ public interface SecureElementListener {
+ /**
+ * Called by the framework when the service is connected.
+ */
+ void onServiceConnected();
+ }
+
+ /**
+ * Listener object that allows the notification of the caller if this
+ * SEService could be bound to the backend.
+ */
+ private class SEListener extends ISecureElementListener.Stub {
+ public SecureElementListener mListener = null;
+
@Override
public IBinder asBinder() {
return this;
}
- /**
- * Called by the framework when the service is connected.
- */
- public void serviceConnected() {};
+ public void onServiceConnected() {
+ if (mListener != null) {
+ mListener.onServiceConnected();
+ }
+ }
}
+ private SEListener mSEListener = new SEListener();
private static final String TAG = "OMAPI.SEService";
@@ -95,34 +110,28 @@
private final HashMap<String, Reader> mReaders = new HashMap<String, Reader>();
/**
- * Listener object that allows the notification of the caller if this
- * SEService could be bound to the backend.
- */
- private ISecureElementListener mSEListener;
-
- /**
* Establishes a new connection that can be used to connect to all the
* Secure Elements available in the system. The connection process can be
* quite long, so it happens in an asynchronous way. It is usable only if
* the specified listener is called or if isConnected() returns
* <code>true</code>. <br>
* The call-back object passed as a parameter will have its
- * serviceConnected() method called when the connection actually happen.
+ * onServiceConnected() method called when the connection actually happen.
*
* @param context
* the context of the calling application. Cannot be
* <code>null</code>.
* @param listener
- * a SecureElementListener object. Can be <code>null</code>.
+ * a SecureElementListener object.
*/
- public SEService(Context context, SecureElementListener listener) {
+ public SEService(@NonNull Context context, @NonNull SecureElementListener listener) {
if (context == null) {
throw new NullPointerException("context must not be null");
}
mContext = context;
- mSEListener = listener;
+ mSEListener.mListener = listener;
mConnection = new ServiceConnection() {
@@ -131,9 +140,7 @@
mSecureElementService = ISecureElementService.Stub.asInterface(service);
if (mSEListener != null) {
- try {
- mSEListener.serviceConnected();
- } catch (RemoteException ignore) { }
+ mSEListener.onServiceConnected();
}
Log.i(TAG, "Service onServiceConnected");
}
@@ -233,7 +240,7 @@
*
* @return String containing the OpenMobile API version (e.g. "3.0").
*/
- public String getVersion() {
+ public @NonNull String getVersion() {
return "3.2";
}
diff --git a/core/java/android/se/omapi/Session.java b/core/java/android/se/omapi/Session.java
index 3d8b74b..adfeddd 100644
--- a/core/java/android/se/omapi/Session.java
+++ b/core/java/android/se/omapi/Session.java
@@ -47,7 +47,8 @@
private final ISecureElementSession mSession;
private static final String TAG = "OMAPI.Session";
- Session(SEService service, ISecureElementSession session, Reader reader) {
+ Session(@NonNull SEService service, @NonNull ISecureElementSession session,
+ @NonNull Reader reader) {
if (service == null || reader == null || session == null) {
throw new IllegalArgumentException("Parameters cannot be null");
}
@@ -195,7 +196,8 @@
* supported by the device
* @return an instance of Channel if available or null.
*/
- public @Nullable Channel openBasicChannel(byte[] aid, byte p2) throws IOException {
+ public @Nullable Channel openBasicChannel(@Nullable byte[] aid, @Nullable byte p2)
+ throws IOException {
if (!mService.isConnected()) {
throw new IllegalStateException("service not connected to system");
}
@@ -223,32 +225,6 @@
}
/**
- * This method is provided to ease the development of mobile application and for compliancy
- * with existing applications.
- * This method is equivalent to openBasicChannel(aid, P2=0x00)
- *
- * @param aid the AID of the Applet to be selected on this channel, as a
- * byte array, or null if no Applet is to be selected.
- * @throws IOException if there is a communication problem to the reader or
- * the Secure Element.
- * @throws IllegalStateException if the Secure Element session is used after
- * being closed.
- * @throws IllegalArgumentException if the aid's length is not within 5 to
- * 16 (inclusive).
- * @throws SecurityException if the calling application cannot be granted
- * access to this AID or the default Applet on this
- * session.
- * @throws NoSuchElementException if the AID on the Secure Element is not available or cannot be
- * selected.
- * @throws UnsupportedOperationException if the given P2 parameter is not
- * supported by the device
- * @return an instance of Channel if available or null.
- */
- public @Nullable Channel openBasicChannel(byte[] aid) throws IOException {
- return openBasicChannel(aid, (byte) 0x00);
- }
-
- /**
* Open a logical channel with the Secure Element, selecting the Applet represented by
* the given AID. If the AID is null, which means no Applet is to be selected on this
* channel, the default Applet is used. It's up to the Secure Element to choose which
@@ -300,7 +276,8 @@
* @return an instance of Channel. Null if the Secure Element is unable to
* provide a new logical channel.
*/
- public @Nullable Channel openLogicalChannel(byte[] aid, byte p2) throws IOException {
+ public @Nullable Channel openLogicalChannel(@Nullable byte[] aid, @Nullable byte p2)
+ throws IOException {
if (!mService.isConnected()) {
throw new IllegalStateException("service not connected to system");
}
@@ -327,32 +304,4 @@
}
}
}
-
- /**
- * This method is provided to ease the development of mobile application and for compliancy
- * with existing applications.
- * This method is equivalent to openLogicalChannel(aid, P2=0x00)
- *
- * @param aid the AID of the Applet to be selected on this channel, as a
- * byte array.
- * @throws IOException if there is a communication problem to the reader or
- * the Secure Element.
- * @throws IllegalStateException if the Secure Element is used after being
- * closed.
- * @throws IllegalArgumentException if the aid's length is not within 5 to
- * 16 (inclusive).
- * @throws SecurityException if the calling application cannot be granted
- * access to this AID or the default Applet on this
- * session.
- * @throws NoSuchElementException if the AID on the Secure Element is not
- * available or cannot be selected or a logical channel is already
- * open to a non-multiselectable Applet.
- * @throws UnsupportedOperationException if the given P2 parameter is not
- * supported by the device.
- * @return an instance of Channel. Null if the Secure Element is unable to
- * provide a new logical channel.
- */
- public @Nullable Channel openLogicalChannel(byte[] aid) throws IOException {
- return openLogicalChannel(aid, (byte) 0x00);
- }
}
diff --git a/core/java/android/text/InputType.java b/core/java/android/text/InputType.java
index f38482e..7f903b6 100644
--- a/core/java/android/text/InputType.java
+++ b/core/java/android/text/InputType.java
@@ -24,7 +24,7 @@
* <h3>Examples</h3>
*
* <dl>
- * <dt>A password field with with the password visible to the user:
+ * <dt>A password field with the password visible to the user:
* <dd>inputType = TYPE_CLASS_TEXT |
* TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
*
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 9687009..eecdb74 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -37,7 +37,6 @@
private static final Map<String, String> DEFAULT_FLAGS;
static {
DEFAULT_FLAGS = new HashMap<>();
- DEFAULT_FLAGS.put("settings_battery_v2", "true");
DEFAULT_FLAGS.put("settings_battery_display_app_list", "false");
DEFAULT_FLAGS.put("settings_zone_picker_v2", "true");
DEFAULT_FLAGS.put("settings_about_phone_v2", "true");
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index d3b1e5c..df81a31 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -250,6 +250,18 @@
}
/**
+ * Destroys the HwuiContext without completely
+ * releasing the Surface.
+ * @hide
+ */
+ public void hwuiDestroy() {
+ if (mHwuiContext != null) {
+ mHwuiContext.destroy();
+ mHwuiContext = null;
+ }
+ }
+
+ /**
* Returns true if this object holds a valid surface.
*
* @return True if it holds a physical surface, so lockCanvas() will succeed.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6393127..f6c669b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -14927,10 +14927,6 @@
* ImageView with only the foreground image. The default implementation returns true; subclasses
* should override if they have cases which can be optimized.</p>
*
- * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
- * necessitates that a View return true if it uses the methods internally without passing the
- * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
- *
* <p><strong>Note:</strong> The return value of this method is ignored if {@link
* #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
*
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index abc19d0..f6181d7 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -236,6 +236,18 @@
int TRANSIT_KEYGUARD_UNOCCLUDE = 23;
/**
+ * A translucent activity is being opened.
+ * @hide
+ */
+ int TRANSIT_TRANSLUCENT_ACTIVITY_OPEN = 24;
+
+ /**
+ * A translucent activity is being closed.
+ * @hide
+ */
+ int TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE = 25;
+
+ /**
* @hide
*/
@IntDef(prefix = { "TRANSIT_" }, value = {
@@ -258,7 +270,9 @@
TRANSIT_KEYGUARD_GOING_AWAY,
TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
TRANSIT_KEYGUARD_OCCLUDE,
- TRANSIT_KEYGUARD_UNOCCLUDE
+ TRANSIT_KEYGUARD_UNOCCLUDE,
+ TRANSIT_TRANSLUCENT_ACTIVITY_OPEN,
+ TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE
})
@Retention(RetentionPolicy.SOURCE)
@interface TransitionType {}
@@ -1833,7 +1847,9 @@
public static final int SOFT_INPUT_MASK_STATE = 0x0f;
/**
- * Visibility state for {@link #softInputMode}: no state has been specified.
+ * Visibility state for {@link #softInputMode}: no state has been specified. The system may
+ * show or hide the software keyboard for better user experience when the window gains
+ * focus.
*/
public static final int SOFT_INPUT_STATE_UNSPECIFIED = 0;
@@ -2220,7 +2236,7 @@
@IntDef(
flag = true,
value = {LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT,
- LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS,
+ LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES,
LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER})
@interface LayoutInDisplayCutoutMode {}
@@ -2231,10 +2247,11 @@
* Defaults to {@link #LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT}.
*
* @see #LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
- * @see #LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
+ * @see #LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
* @see #LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
* @see DisplayCutout
- * @see android.R.attr#layoutInDisplayCutoutMode
+ * @see android.R.attr#windowLayoutInDisplayCutoutMode
+ * android:windowLayoutInDisplayCutoutMode
*/
@LayoutInDisplayCutoutMode
public int layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
@@ -2245,10 +2262,10 @@
* laid out such that it does not overlap with the {@link DisplayCutout} area.
*
* <p>
- * In practice, this means that if the window did not set FLAG_FULLSCREEN or
- * SYSTEM_UI_FLAG_FULLSCREEN, it can extend into the cutout area in portrait if the cutout
- * is at the top edge. Similarly for SYSTEM_UI_FLAG_HIDE_NAVIGATION and a cutout at the
- * bottom of the screen.
+ * In practice, this means that if the window did not set {@link #FLAG_FULLSCREEN} or
+ * {@link View#SYSTEM_UI_FLAG_FULLSCREEN}, it can extend into the cutout area in portrait
+ * if the cutout is at the top edge. Similarly for
+ * {@link View#SYSTEM_UI_FLAG_HIDE_NAVIGATION} and a cutout at the bottom of the screen.
* Otherwise (i.e. fullscreen or landscape) it is laid out such that it does not overlap the
* cutout area.
*
@@ -2258,6 +2275,9 @@
*
* @see DisplayCutout
* @see WindowInsets
+ * @see #layoutInDisplayCutoutMode
+ * @see android.R.attr#windowLayoutInDisplayCutoutMode
+ * android:windowLayoutInDisplayCutoutMode
*/
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT = 0;
@@ -2279,8 +2299,40 @@
* The window must make sure that no important content overlaps with the
* {@link DisplayCutout}.
*
+ * <p>
+ * In this mode, the window extends under cutouts on the short edge of the display in both
+ * portrait and landscape, regardless of whether the window is hiding the system bars:<br/>
+ * <img src="{@docRoot}reference/android/images/display_cutout/short_edge/fullscreen_top_no_letterbox.png"
+ * height="720"
+ * alt="Screenshot of a fullscreen activity on a display with a cutout at the top edge in
+ * portrait, no letterbox is applied."/>
+ *
+ * <img src="{@docRoot}reference/android/images/display_cutout/short_edge/landscape_top_no_letterbox.png"
+ * width="720"
+ * alt="Screenshot of an activity on a display with a cutout at the top edge in landscape,
+ * no letterbox is applied."/>
+ *
+ * <p>
+ * A cutout in the corner is considered to be on the short edge: <br/>
+ * <img src="{@docRoot}reference/android/images/display_cutout/short_edge/fullscreen_corner_no_letterbox.png"
+ * height="720"
+ * alt="Screenshot of a fullscreen activity on a display with a cutout in the corner in
+ * portrait, no letterbox is applied."/>
+ *
+ * <p>
+ * On the other hand, should the cutout be on the long edge of the display, a letterbox will
+ * be applied such that the window does not extend into the cutout on either long edge:
+ * <br/>
+ * <img src="{@docRoot}reference/android/images/display_cutout/short_edge/portrait_side_letterbox.png"
+ * height="720"
+ * alt="Screenshot of an activity on a display with a cutout on the long edge in portrait,
+ * letterbox is applied."/>
+ *
* @see DisplayCutout
* @see WindowInsets#getDisplayCutout()
+ * @see #layoutInDisplayCutoutMode
+ * @see android.R.attr#windowLayoutInDisplayCutoutMode
+ * android:windowLayoutInDisplayCutoutMode
*/
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES = 1;
@@ -2288,12 +2340,14 @@
* The window is never allowed to overlap with the DisplayCutout area.
*
* <p>
- * This should be used with windows that transiently set SYSTEM_UI_FLAG_FULLSCREEN to
- * avoid a relayout of the window when the flag is set or cleared.
+ * This should be used with windows that transiently set
+ * {@link View#SYSTEM_UI_FLAG_FULLSCREEN} or {@link View#SYSTEM_UI_FLAG_HIDE_NAVIGATION}
+ * to avoid a relayout of the window when the respective flag is set or cleared.
*
* @see DisplayCutout
- * @see View#SYSTEM_UI_FLAG_FULLSCREEN SYSTEM_UI_FLAG_FULLSCREEN
- * @see View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ * @see #layoutInDisplayCutoutMode
+ * @see android.R.attr#windowLayoutInDisplayCutoutMode
+ * android:windowLayoutInDisplayCutoutMode
*/
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER = 2;
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 01fd090..88300db 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1819,13 +1819,22 @@
final View[] views = client.autofillClientFindViewsByAutofillIdTraversal(
Helper.toArray(ids));
+ ArrayList<AutofillId> failedIds = null;
+
for (int i = 0; i < itemCount; i++) {
final AutofillId id = ids.get(i);
final AutofillValue value = values.get(i);
final int viewId = id.getViewId();
final View view = views[i];
if (view == null) {
- Log.w(TAG, "autofill(): no View with id " + viewId);
+ // Most likely view has been removed after the initial request was sent to the
+ // the service; this is fine, but we need to update the view status in the
+ // server side so it can be triggered again.
+ Log.d(TAG, "autofill(): no View with id " + id);
+ if (failedIds == null) {
+ failedIds = new ArrayList<>();
+ }
+ failedIds.add(id);
continue;
}
if (id.isVirtual()) {
@@ -1859,12 +1868,28 @@
}
}
+ if (failedIds != null) {
+ if (sVerbose) {
+ Log.v(TAG, "autofill(): total failed views: " + failedIds);
+ }
+ try {
+ mService.setAutofillFailure(mSessionId, failedIds, mContext.getUserId());
+ } catch (RemoteException e) {
+ // In theory, we could ignore this error since it's not a big deal, but
+ // in reality, we rather crash the app anyways, as the failure could be
+ // a consequence of something going wrong on the server side...
+ e.rethrowFromSystemServer();
+ }
+ }
+
if (virtualValues != null) {
for (int i = 0; i < virtualValues.size(); i++) {
final View parent = virtualValues.keyAt(i);
final SparseArray<AutofillValue> childrenValues = virtualValues.valueAt(i);
parent.autofill(childrenValues);
numApplied += childrenValues.size();
+ // TODO: we should provide a callback so the parent can call failures; something
+ // like notifyAutofillFailed(View view, int[] childrenIds);
}
}
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 56f79ab..176df73 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -16,6 +16,8 @@
package android.view.autofill;
+import java.util.List;
+
import android.content.ComponentName;
import android.graphics.Rect;
import android.os.Bundle;
@@ -47,6 +49,7 @@
in AutofillId autoFillId, in Rect bounds, in AutofillValue value, int userId,
boolean hasCallback, int flags, in ComponentName componentName, int sessionId,
int action, boolean compatMode);
+ void setAutofillFailure(int sessionId, in List<AutofillId> ids, int userId);
void finishSession(int sessionId, int userId);
void cancelSession(int sessionId, int userId);
void setAuthenticationResult(in Bundle data, int sessionId, int authenticationId, int userId);
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index b5c9de9..630007b 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -21,6 +21,8 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.app.RemoteAction;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -43,6 +45,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Calendar;
+import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -77,25 +80,16 @@
* view.startActionMode(new ActionMode.Callback() {
*
* public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- * // Add the "primary" action.
- * if (thisAppHasPermissionToInvokeIntent(classification.getIntent())) {
- * menu.add(Menu.NONE, 0, 20, classification.getLabel())
- * .setIcon(classification.getIcon())
- * .setIntent(classification.getIntent());
- * }
- * // Add the "secondary" actions.
- * for (int i = 0; i < classification.getSecondaryActionsCount(); i++) {
- * if (thisAppHasPermissionToInvokeIntent(classification.getSecondaryIntent(i))) {
- * menu.add(Menu.NONE, i + 1, 20, classification.getSecondaryLabel(i))
- * .setIcon(classification.getSecondaryIcon(i))
- * .setIntent(classification.getSecondaryIntent(i));
- * }
+ * for (int i = 0; i < classification.getActions().size(); ++i) {
+ * RemoteAction action = classification.getActions().get(i);
+ * menu.add(Menu.NONE, i, 20, action.getTitle())
+ * .setIcon(action.getIcon());
* }
* return true;
* }
*
* public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- * context.startActivity(item.getIntent());
+ * classification.getActions().get(item.getItemId()).getActionIntent().send();
* return true;
* }
*
@@ -110,9 +104,9 @@
*/
static final TextClassification EMPTY = new TextClassification.Builder().build();
+ private static final String LOG_TAG = "TextClassification";
// TODO(toki): investigate a way to derive this based on device properties.
- private static final int MAX_PRIMARY_ICON_SIZE = 192;
- private static final int MAX_SECONDARY_ICON_SIZE = 144;
+ private static final int MAX_LEGACY_ICON_SIZE = 192;
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {IntentType.UNSUPPORTED, IntentType.ACTIVITY, IntentType.SERVICE})
@@ -123,37 +117,29 @@
}
@NonNull private final String mText;
- @Nullable private final Drawable mPrimaryIcon;
- @Nullable private final String mPrimaryLabel;
- @Nullable private final Intent mPrimaryIntent;
- @Nullable private final OnClickListener mPrimaryOnClickListener;
- @NonNull private final List<Drawable> mSecondaryIcons;
- @NonNull private final List<String> mSecondaryLabels;
- @NonNull private final List<Intent> mSecondaryIntents;
+ @Nullable private final Drawable mLegacyIcon;
+ @Nullable private final String mLegacyLabel;
+ @Nullable private final Intent mLegacyIntent;
+ @Nullable private final OnClickListener mLegacyOnClickListener;
+ @NonNull private final List<RemoteAction> mActions;
@NonNull private final EntityConfidence mEntityConfidence;
@NonNull private final String mSignature;
private TextClassification(
@Nullable String text,
- @Nullable Drawable primaryIcon,
- @Nullable String primaryLabel,
- @Nullable Intent primaryIntent,
- @Nullable OnClickListener primaryOnClickListener,
- @NonNull List<Drawable> secondaryIcons,
- @NonNull List<String> secondaryLabels,
- @NonNull List<Intent> secondaryIntents,
+ @Nullable Drawable legacyIcon,
+ @Nullable String legacyLabel,
+ @Nullable Intent legacyIntent,
+ @Nullable OnClickListener legacyOnClickListener,
+ @NonNull List<RemoteAction> actions,
@NonNull Map<String, Float> entityConfidence,
@NonNull String signature) {
- Preconditions.checkArgument(secondaryLabels.size() == secondaryIntents.size());
- Preconditions.checkArgument(secondaryIcons.size() == secondaryIntents.size());
mText = text;
- mPrimaryIcon = primaryIcon;
- mPrimaryLabel = primaryLabel;
- mPrimaryIntent = primaryIntent;
- mPrimaryOnClickListener = primaryOnClickListener;
- mSecondaryIcons = secondaryIcons;
- mSecondaryLabels = secondaryLabels;
- mSecondaryIntents = secondaryIntents;
+ mLegacyIcon = legacyIcon;
+ mLegacyLabel = legacyLabel;
+ mLegacyIntent = legacyIntent;
+ mLegacyOnClickListener = legacyOnClickListener;
+ mActions = Collections.unmodifiableList(actions);
mEntityConfidence = new EntityConfidence(entityConfidence);
mSignature = signature;
}
@@ -197,108 +183,57 @@
}
/**
- * Returns the number of <i>secondary</i> actions that are available to act on the classified
- * text.
- *
- * <p><strong>Note: </strong> that there may or may not be a <i>primary</i> action.
- *
- * @see #getSecondaryIntent(int)
- * @see #getSecondaryLabel(int)
- * @see #getSecondaryIcon(int)
+ * Returns a list of actions that may be performed on the text. The list is ordered based on
+ * the likelihood that a user will use the action, with the most likely action appearing first.
*/
- @IntRange(from = 0)
- public int getSecondaryActionsCount() {
- return mSecondaryIntents.size();
+ public List<RemoteAction> getActions() {
+ return mActions;
}
/**
- * Returns one of the <i>secondary</i> icons that maybe rendered on a widget used to act on the
- * classified text.
+ * Returns an icon that may be rendered on a widget used to act on the classified text.
*
- * @param index Index of the action to get the icon for.
- * @throws IndexOutOfBoundsException if the specified index is out of range.
- * @see #getSecondaryActionsCount() for the number of actions available.
- * @see #getSecondaryIntent(int)
- * @see #getSecondaryLabel(int)
- * @see #getIcon()
+ * @deprecated Use {@link #getActions()} instead.
*/
- @Nullable
- public Drawable getSecondaryIcon(int index) {
- return mSecondaryIcons.get(index);
- }
-
- /**
- * Returns an icon for the <i>primary</i> intent that may be rendered on a widget used to act
- * on the classified text.
- *
- * @see #getSecondaryIcon(int)
- */
+ @Deprecated
@Nullable
public Drawable getIcon() {
- return mPrimaryIcon;
+ return mLegacyIcon;
}
/**
- * Returns one of the <i>secondary</i> labels that may be rendered on a widget used to act on
- * the classified text.
+ * Returns a label that may be rendered on a widget used to act on the classified text.
*
- * @param index Index of the action to get the label for.
- * @throws IndexOutOfBoundsException if the specified index is out of range.
- * @see #getSecondaryActionsCount()
- * @see #getSecondaryIntent(int)
- * @see #getSecondaryIcon(int)
- * @see #getLabel()
+ * @deprecated Use {@link #getActions()} instead.
*/
- @Nullable
- public CharSequence getSecondaryLabel(int index) {
- return mSecondaryLabels.get(index);
- }
-
- /**
- * Returns a label for the <i>primary</i> intent that may be rendered on a widget used to act
- * on the classified text.
- *
- * @see #getSecondaryLabel(int)
- */
+ @Deprecated
@Nullable
public CharSequence getLabel() {
- return mPrimaryLabel;
+ return mLegacyLabel;
}
/**
- * Returns one of the <i>secondary</i> intents that may be fired to act on the classified text.
+ * Returns an intent that may be fired to act on the classified text.
*
- * @param index Index of the action to get the intent for.
- * @throws IndexOutOfBoundsException if the specified index is out of range.
- * @see #getSecondaryActionsCount()
- * @see #getSecondaryLabel(int)
- * @see #getSecondaryIcon(int)
- * @see #getIntent()
+ * @deprecated Use {@link #getActions()} instead.
*/
- @Nullable
- public Intent getSecondaryIntent(int index) {
- return mSecondaryIntents.get(index);
- }
-
- /**
- * Returns the <i>primary</i> intent that may be fired to act on the classified text.
- *
- * @see #getSecondaryIntent(int)
- */
+ @Deprecated
@Nullable
public Intent getIntent() {
- return mPrimaryIntent;
+ return mLegacyIntent;
}
/**
- * Returns the <i>primary</i> OnClickListener that may be triggered to act on the classified
- * text. This field is not parcelable and will be null for all objects read from a parcel.
- * Instead, call Context#startActivity(Intent) with the result of #getSecondaryIntent(int).
- * Note that this may fail if the activity doesn't have permission to send the intent.
+ * Returns the OnClickListener that may be triggered to act on the classified text. This field
+ * is not parcelable and will be null for all objects read from a parcel. Instead, call
+ * Context#startActivity(Intent) with the result of #getSecondaryIntent(int). Note that this may
+ * fail if the activity doesn't have permission to send the intent.
+ *
+ * @deprecated Use {@link #getActions()} instead.
*/
@Nullable
public OnClickListener getOnClickListener() {
- return mPrimaryOnClickListener;
+ return mLegacyOnClickListener;
}
/**
@@ -313,32 +248,42 @@
@Override
public String toString() {
- return String.format(Locale.US, "TextClassification {"
- + "text=%s, entities=%s, "
- + "primaryLabel=%s, secondaryLabels=%s, "
- + "primaryIntent=%s, secondaryIntents=%s, "
- + "signature=%s}",
- mText, mEntityConfidence,
- mPrimaryLabel, mSecondaryLabels,
- mPrimaryIntent, mSecondaryIntents,
- mSignature);
+ return String.format(Locale.US,
+ "TextClassification {text=%s, entities=%s, actions=%s, signature=%s}",
+ mText, mEntityConfidence, mActions, mSignature);
}
/**
- * Creates an OnClickListener that triggers the specified intent.
+ * Creates an OnClickListener that triggers the specified PendingIntent.
+ *
+ * @hide
+ */
+ public static OnClickListener createIntentOnClickListener(@NonNull final PendingIntent intent) {
+ Preconditions.checkNotNull(intent);
+ return v -> {
+ try {
+ intent.send();
+ } catch (PendingIntent.CanceledException e) {
+ Log.e(LOG_TAG, "Error creating OnClickListener from PendingIntent", e);
+ }
+ };
+ }
+
+ /**
+ * Creates a PendingIntent for the specified intent.
* Returns null if the intent is not supported for the specified context.
*
* @throws IllegalArgumentException if context or intent is null
* @hide
*/
@Nullable
- public static OnClickListener createIntentOnClickListener(
+ public static PendingIntent createPendingIntent(
@NonNull final Context context, @NonNull final Intent intent) {
switch (getIntentType(intent, context)) {
case IntentType.ACTIVITY:
- return v -> context.startActivity(intent);
+ return PendingIntent.getActivity(context, 0, intent, 0);
case IntentType.SERVICE:
- return v -> context.startService(intent);
+ return PendingIntent.getService(context, 0, intent, 0);
default:
return null;
}
@@ -434,33 +379,6 @@
}
/**
- * Returns a list of drawables converted to Bitmaps
- *
- * @param drawables The drawables to convert.
- * @param maxDims The maximum edge length of the resulting bitmaps (in pixels).
- */
- private static List<Bitmap> drawablesToBitmaps(List<Drawable> drawables, int maxDims) {
- final List<Bitmap> bitmaps = new ArrayList<>(drawables.size());
- for (Drawable drawable : drawables) {
- bitmaps.add(drawableToBitmap(drawable, maxDims));
- }
- return bitmaps;
- }
-
- /** Returns a list of drawable wrappers for a list of bitmaps. */
- private static List<Drawable> bitmapsToDrawables(List<Bitmap> bitmaps) {
- final List<Drawable> drawables = new ArrayList<>(bitmaps.size());
- for (Bitmap bitmap : bitmaps) {
- if (bitmap != null) {
- drawables.add(new BitmapDrawable(Resources.getSystem(), bitmap));
- } else {
- drawables.add(null);
- }
- }
- return drawables;
- }
-
- /**
* Builder for building {@link TextClassification} objects.
*
* <p>e.g.
@@ -470,23 +388,20 @@
* .setText(classifiedText)
* .setEntityType(TextClassifier.TYPE_EMAIL, 0.9)
* .setEntityType(TextClassifier.TYPE_OTHER, 0.1)
- * .setPrimaryAction(intent, label, icon)
- * .addSecondaryAction(intent1, label1, icon1)
- * .addSecondaryAction(intent2, label2, icon2)
+ * .addAction(remoteAction1)
+ * .addAction(remoteAction2)
* .build();
* }</pre>
*/
public static final class Builder {
@NonNull private String mText;
- @NonNull private final List<Drawable> mSecondaryIcons = new ArrayList<>();
- @NonNull private final List<String> mSecondaryLabels = new ArrayList<>();
- @NonNull private final List<Intent> mSecondaryIntents = new ArrayList<>();
+ @NonNull private List<RemoteAction> mActions = new ArrayList<>();
@NonNull private final Map<String, Float> mEntityConfidence = new ArrayMap<>();
- @Nullable Drawable mPrimaryIcon;
- @Nullable String mPrimaryLabel;
- @Nullable Intent mPrimaryIntent;
- @Nullable OnClickListener mPrimaryOnClickListener;
+ @Nullable Drawable mLegacyIcon;
+ @Nullable String mLegacyLabel;
+ @Nullable Intent mLegacyIntent;
+ @Nullable OnClickListener mLegacyOnClickListener;
@NonNull private String mSignature = "";
/**
@@ -514,60 +429,25 @@
}
/**
- * Adds an <i>secondary</i> action that may be performed on the classified text.
- * Secondary actions are in addition to the <i>primary</i> action which may or may not
- * exist.
- *
- * <p>The label and icon are used for rendering of widgets that offer the intent.
- * Actions should be added in order of priority.
- *
- * <p><stong>Note: </stong> If all input parameters are set to null, this method will be a
- * no-op.
- *
- * @see #setPrimaryAction(Intent, String, Drawable)
+ * Adds an action that may be performed on the classified text. Actions should be added in
+ * order of likelihood that the user will use them, with the most likely action being added
+ * first.
*/
- public Builder addSecondaryAction(
- @Nullable Intent intent, @Nullable String label, @Nullable Drawable icon) {
- if (intent != null || label != null || icon != null) {
- mSecondaryIntents.add(intent);
- mSecondaryLabels.add(label);
- mSecondaryIcons.add(icon);
- }
+ public Builder addAction(@NonNull RemoteAction action) {
+ Preconditions.checkArgument(action != null);
+ mActions.add(action);
return this;
}
/**
- * Removes all the <i>secondary</i> actions.
- */
- public Builder clearSecondaryActions() {
- mSecondaryIntents.clear();
- mSecondaryLabels.clear();
- mSecondaryIcons.clear();
- return this;
- }
-
- /**
- * Sets the <i>primary</i> action that may be performed on the classified text. This is
- * equivalent to calling {@code setIntent(intent).setLabel(label).setIcon(icon)}.
- *
- * <p><strong>Note: </strong>If all input parameters are null, there will be no
- * <i>primary</i> action but there may still be <i>secondary</i> actions.
- *
- * @see #addSecondaryAction(Intent, String, Drawable)
- */
- public Builder setPrimaryAction(
- @Nullable Intent intent, @Nullable String label, @Nullable Drawable icon) {
- return setIntent(intent).setLabel(label).setIcon(icon);
- }
-
- /**
* Sets the icon for the <i>primary</i> action that may be rendered on a widget used to act
* on the classified text.
*
- * @see #setPrimaryAction(Intent, String, Drawable)
+ * @deprecated Use {@link #addAction(RemoteAction)} instead.
*/
+ @Deprecated
public Builder setIcon(@Nullable Drawable icon) {
- mPrimaryIcon = icon;
+ mLegacyIcon = icon;
return this;
}
@@ -575,10 +455,11 @@
* Sets the label for the <i>primary</i> action that may be rendered on a widget used to
* act on the classified text.
*
- * @see #setPrimaryAction(Intent, String, Drawable)
+ * @deprecated Use {@link #addAction(RemoteAction)} instead.
*/
+ @Deprecated
public Builder setLabel(@Nullable String label) {
- mPrimaryLabel = label;
+ mLegacyLabel = label;
return this;
}
@@ -586,10 +467,11 @@
* Sets the intent for the <i>primary</i> action that may be fired to act on the classified
* text.
*
- * @see #setPrimaryAction(Intent, String, Drawable)
+ * @deprecated Use {@link #addAction(RemoteAction)} instead.
*/
+ @Deprecated
public Builder setIntent(@Nullable Intent intent) {
- mPrimaryIntent = intent;
+ mLegacyIntent = intent;
return this;
}
@@ -597,9 +479,11 @@
* Sets the OnClickListener for the <i>primary</i> action that may be triggered to act on
* the classified text. This field is not parcelable and will always be null when the
* object is read from a parcel.
+ *
+ * @deprecated Use {@link #addAction(RemoteAction)} instead.
*/
public Builder setOnClickListener(@Nullable OnClickListener onClickListener) {
- mPrimaryOnClickListener = onClickListener;
+ mLegacyOnClickListener = onClickListener;
return this;
}
@@ -617,11 +501,8 @@
* Builds and returns a {@link TextClassification} object.
*/
public TextClassification build() {
- return new TextClassification(
- mText,
- mPrimaryIcon, mPrimaryLabel, mPrimaryIntent, mPrimaryOnClickListener,
- mSecondaryIcons, mSecondaryLabels, mSecondaryIntents,
- mEntityConfidence, mSignature);
+ return new TextClassification(mText, mLegacyIcon, mLegacyLabel, mLegacyIntent,
+ mLegacyOnClickListener, mActions, mEntityConfidence, mSignature);
}
}
@@ -721,20 +602,18 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mText);
- final Bitmap primaryIconBitmap = drawableToBitmap(mPrimaryIcon, MAX_PRIMARY_ICON_SIZE);
- dest.writeInt(primaryIconBitmap != null ? 1 : 0);
- if (primaryIconBitmap != null) {
- primaryIconBitmap.writeToParcel(dest, flags);
+ final Bitmap legacyIconBitmap = drawableToBitmap(mLegacyIcon, MAX_LEGACY_ICON_SIZE);
+ dest.writeInt(legacyIconBitmap != null ? 1 : 0);
+ if (legacyIconBitmap != null) {
+ legacyIconBitmap.writeToParcel(dest, flags);
}
- dest.writeString(mPrimaryLabel);
- dest.writeInt(mPrimaryIntent != null ? 1 : 0);
- if (mPrimaryIntent != null) {
- mPrimaryIntent.writeToParcel(dest, flags);
+ dest.writeString(mLegacyLabel);
+ dest.writeInt(mLegacyIntent != null ? 1 : 0);
+ if (mLegacyIntent != null) {
+ mLegacyIntent.writeToParcel(dest, flags);
}
- // mPrimaryOnClickListener is not parcelable.
- dest.writeTypedList(drawablesToBitmaps(mSecondaryIcons, MAX_SECONDARY_ICON_SIZE));
- dest.writeStringList(mSecondaryLabels);
- dest.writeTypedList(mSecondaryIntents);
+ // mOnClickListener is not parcelable.
+ dest.writeTypedList(mActions);
mEntityConfidence.writeToParcel(dest, flags);
dest.writeString(mSignature);
}
@@ -754,15 +633,19 @@
private TextClassification(Parcel in) {
mText = in.readString();
- mPrimaryIcon = in.readInt() == 0
+ mLegacyIcon = in.readInt() == 0
? null
: new BitmapDrawable(Resources.getSystem(), Bitmap.CREATOR.createFromParcel(in));
- mPrimaryLabel = in.readString();
- mPrimaryIntent = in.readInt() == 0 ? null : Intent.CREATOR.createFromParcel(in);
- mPrimaryOnClickListener = null; // not parcelable
- mSecondaryIcons = bitmapsToDrawables(in.createTypedArrayList(Bitmap.CREATOR));
- mSecondaryLabels = in.createStringArrayList();
- mSecondaryIntents = in.createTypedArrayList(Intent.CREATOR);
+ mLegacyLabel = in.readString();
+ if (in.readInt() == 0) {
+ mLegacyIntent = null;
+ } else {
+ mLegacyIntent = Intent.CREATOR.createFromParcel(in);
+ mLegacyIntent.removeFlags(
+ Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ }
+ mLegacyOnClickListener = null; // not parcelable
+ mActions = in.createTypedArrayList(RemoteAction.CREATOR);
mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in);
mSignature = in.readString();
}
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index c2fb032..a0f4d5c 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.WorkerThread;
+import android.app.RemoteAction;
import android.app.SearchManager;
import android.content.ComponentName;
import android.content.ContentUris;
@@ -26,7 +27,7 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Bundle;
import android.os.LocaleList;
@@ -418,50 +419,27 @@
}
}
- addActions(builder, IntentFactory.create(
- mContext, referenceTime, highestScoringResult, classifiedText));
+ boolean isPrimaryAction = true;
+ for (LabeledIntent labeledIntent : IntentFactory.create(
+ mContext, referenceTime, highestScoringResult, classifiedText)) {
+ RemoteAction action = labeledIntent.asRemoteAction(mContext);
+ if (isPrimaryAction) {
+ // For O backwards compatibility, the first RemoteAction is also written to the
+ // legacy API fields.
+ builder.setIcon(action.getIcon().loadDrawable(mContext));
+ builder.setLabel(action.getTitle().toString());
+ builder.setIntent(labeledIntent.getIntent());
+ builder.setOnClickListener(TextClassification.createIntentOnClickListener(
+ TextClassification.createPendingIntent(mContext,
+ labeledIntent.getIntent())));
+ isPrimaryAction = false;
+ }
+ builder.addAction(action);
+ }
return builder.setSignature(getSignature(text, start, end)).build();
}
- /** Extends the classification with the intents that can be resolved. */
- private void addActions(
- TextClassification.Builder builder, List<Intent> intents) {
- final PackageManager pm = mContext.getPackageManager();
- final int size = intents.size();
- for (int i = 0; i < size; i++) {
- final Intent intent = intents.get(i);
- final ResolveInfo resolveInfo;
- if (intent != null) {
- resolveInfo = pm.resolveActivity(intent, 0);
- } else {
- resolveInfo = null;
- }
- if (resolveInfo != null && resolveInfo.activityInfo != null) {
- final String packageName = resolveInfo.activityInfo.packageName;
- final String label = IntentFactory.getLabel(mContext, intent);
- Drawable icon;
- if ("android".equals(packageName)) {
- // Requires the chooser to find an activity to handle the intent.
- icon = null;
- } else {
- // A default activity will handle the intent.
- intent.setComponent(
- new ComponentName(packageName, resolveInfo.activityInfo.name));
- icon = resolveInfo.activityInfo.loadIcon(pm);
- if (icon == null) {
- icon = resolveInfo.loadIcon(pm);
- }
- }
- if (i == 0) {
- builder.setPrimaryAction(intent, label, icon);
- } else {
- builder.addSecondaryAction(intent, label, icon);
- }
- }
- }
- }
-
/**
* Closes the ParcelFileDescriptor and logs any errors that occur.
*/
@@ -588,6 +566,60 @@
}
/**
+ * Helper class to store the information from which RemoteActions are built.
+ */
+ private static final class LabeledIntent {
+ private String mTitle;
+ private String mDescription;
+ private Intent mIntent;
+
+ LabeledIntent(String title, String description, Intent intent) {
+ mTitle = title;
+ mDescription = description;
+ mIntent = intent;
+ }
+
+ String getTitle() {
+ return mTitle;
+ }
+
+ String getDescription() {
+ return mDescription;
+ }
+
+ Intent getIntent() {
+ return mIntent;
+ }
+
+ RemoteAction asRemoteAction(Context context) {
+ final PackageManager pm = context.getPackageManager();
+ final ResolveInfo resolveInfo = pm.resolveActivity(mIntent, 0);
+ final String packageName = resolveInfo != null && resolveInfo.activityInfo != null
+ ? resolveInfo.activityInfo.packageName : null;
+ Icon icon = null;
+ boolean shouldShowIcon = false;
+ if (packageName != null && !"android".equals(packageName)) {
+ // There is a default activity handling the intent.
+ mIntent.setComponent(new ComponentName(packageName, resolveInfo.activityInfo.name));
+ if (resolveInfo.activityInfo.getIconResource() != 0) {
+ icon = Icon.createWithResource(
+ packageName, resolveInfo.activityInfo.getIconResource());
+ shouldShowIcon = true;
+ }
+ }
+ if (icon == null) {
+ // RemoteAction requires that there be an icon.
+ icon = Icon.createWithResource("android",
+ com.android.internal.R.drawable.ic_more_items);
+ }
+ RemoteAction action = new RemoteAction(icon, mTitle, mDescription,
+ TextClassification.createPendingIntent(context, mIntent));
+ action.setShouldShowIcon(shouldShowIcon);
+ return action;
+ }
+ }
+
+ /**
* Creates intents based on the classification type.
*/
static final class IntentFactory {
@@ -598,7 +630,7 @@
private IntentFactory() {}
@NonNull
- public static List<Intent> create(
+ public static List<LabeledIntent> create(
Context context,
@Nullable Calendar referenceTime,
TextClassifierImplNative.ClassificationResult classification,
@@ -607,11 +639,11 @@
text = text.trim();
switch (type) {
case TextClassifier.TYPE_EMAIL:
- return createForEmail(text);
+ return createForEmail(context, text);
case TextClassifier.TYPE_PHONE:
return createForPhone(context, text);
case TextClassifier.TYPE_ADDRESS:
- return createForAddress(text);
+ return createForAddress(context, text);
case TextClassifier.TYPE_URL:
return createForUrl(context, text);
case TextClassifier.TYPE_DATE:
@@ -620,62 +652,80 @@
Calendar eventTime = Calendar.getInstance();
eventTime.setTimeInMillis(
classification.getDatetimeResult().getTimeMsUtc());
- return createForDatetime(type, referenceTime, eventTime);
+ return createForDatetime(context, type, referenceTime, eventTime);
} else {
return new ArrayList<>();
}
case TextClassifier.TYPE_FLIGHT_NUMBER:
- return createForFlight(text);
+ return createForFlight(context, text);
default:
return new ArrayList<>();
}
}
@NonNull
- private static List<Intent> createForEmail(String text) {
+ private static List<LabeledIntent> createForEmail(Context context, String text) {
return Arrays.asList(
- new Intent(Intent.ACTION_SENDTO)
- .setData(Uri.parse(String.format("mailto:%s", text))),
- new Intent(Intent.ACTION_INSERT_OR_EDIT)
- .setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE)
- .putExtra(ContactsContract.Intents.Insert.EMAIL, text));
+ new LabeledIntent(
+ context.getString(com.android.internal.R.string.email),
+ context.getString(com.android.internal.R.string.email_desc),
+ new Intent(Intent.ACTION_SENDTO)
+ .setData(Uri.parse(String.format("mailto:%s", text)))),
+ new LabeledIntent(
+ context.getString(com.android.internal.R.string.add_contact),
+ context.getString(com.android.internal.R.string.add_contact_desc),
+ new Intent(Intent.ACTION_INSERT_OR_EDIT)
+ .setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE)
+ .putExtra(ContactsContract.Intents.Insert.EMAIL, text)));
}
@NonNull
- private static List<Intent> createForPhone(Context context, String text) {
- final List<Intent> intents = new ArrayList<>();
+ private static List<LabeledIntent> createForPhone(Context context, String text) {
+ final List<LabeledIntent> actions = new ArrayList<>();
final UserManager userManager = context.getSystemService(UserManager.class);
final Bundle userRestrictions = userManager != null
? userManager.getUserRestrictions() : new Bundle();
if (!userRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS, false)) {
- intents.add(new Intent(Intent.ACTION_DIAL)
- .setData(Uri.parse(String.format("tel:%s", text))));
+ actions.add(new LabeledIntent(
+ context.getString(com.android.internal.R.string.dial),
+ context.getString(com.android.internal.R.string.dial_desc),
+ new Intent(Intent.ACTION_DIAL).setData(
+ Uri.parse(String.format("tel:%s", text)))));
}
- intents.add(new Intent(Intent.ACTION_INSERT_OR_EDIT)
- .setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE)
- .putExtra(ContactsContract.Intents.Insert.PHONE, text));
+ actions.add(new LabeledIntent(
+ context.getString(com.android.internal.R.string.add_contact),
+ context.getString(com.android.internal.R.string.add_contact_desc),
+ new Intent(Intent.ACTION_INSERT_OR_EDIT)
+ .setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE)
+ .putExtra(ContactsContract.Intents.Insert.PHONE, text)));
if (!userRestrictions.getBoolean(UserManager.DISALLOW_SMS, false)) {
- intents.add(new Intent(Intent.ACTION_SENDTO)
- .setData(Uri.parse(String.format("smsto:%s", text))));
+ actions.add(new LabeledIntent(
+ context.getString(com.android.internal.R.string.sms),
+ context.getString(com.android.internal.R.string.sms_desc),
+ new Intent(Intent.ACTION_SENDTO)
+ .setData(Uri.parse(String.format("smsto:%s", text)))));
}
- return intents;
+ return actions;
}
@NonNull
- private static List<Intent> createForAddress(String text) {
- final List<Intent> intents = new ArrayList<>();
+ private static List<LabeledIntent> createForAddress(Context context, String text) {
+ final List<LabeledIntent> actions = new ArrayList<>();
try {
final String encText = URLEncoder.encode(text, "UTF-8");
- intents.add(new Intent(Intent.ACTION_VIEW)
- .setData(Uri.parse(String.format("geo:0,0?q=%s", encText))));
+ actions.add(new LabeledIntent(
+ context.getString(com.android.internal.R.string.map),
+ context.getString(com.android.internal.R.string.map_desc),
+ new Intent(Intent.ACTION_VIEW)
+ .setData(Uri.parse(String.format("geo:0,0?q=%s", encText)))));
} catch (UnsupportedEncodingException e) {
Log.e(LOG_TAG, "Could not encode address", e);
}
- return intents;
+ return actions;
}
@NonNull
- private static List<Intent> createForUrl(Context context, String text) {
+ private static List<LabeledIntent> createForUrl(Context context, String text) {
final String httpPrefix = "http://";
final String httpsPrefix = "https://";
if (text.toLowerCase().startsWith(httpPrefix)) {
@@ -685,99 +735,65 @@
} else {
text = httpPrefix + text;
}
- return Arrays.asList(new Intent(Intent.ACTION_VIEW, Uri.parse(text))
- .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()));
+ return Arrays.asList(new LabeledIntent(
+ context.getString(com.android.internal.R.string.browse),
+ context.getString(com.android.internal.R.string.browse_desc),
+ new Intent(Intent.ACTION_VIEW, Uri.parse(text))
+ .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName())));
}
@NonNull
- private static List<Intent> createForDatetime(
- String type, @Nullable Calendar referenceTime, Calendar eventTime) {
+ private static List<LabeledIntent> createForDatetime(
+ Context context, String type, @Nullable Calendar referenceTime,
+ Calendar eventTime) {
if (referenceTime == null) {
// If no reference time was given, use now.
referenceTime = Calendar.getInstance();
}
- List<Intent> intents = new ArrayList<>();
- intents.add(createCalendarViewIntent(eventTime));
+ List<LabeledIntent> actions = new ArrayList<>();
+ actions.add(createCalendarViewIntent(context, eventTime));
final long millisSinceReference =
eventTime.getTimeInMillis() - referenceTime.getTimeInMillis();
if (millisSinceReference > MIN_EVENT_FUTURE_MILLIS) {
- intents.add(createCalendarCreateEventIntent(eventTime, type));
+ actions.add(createCalendarCreateEventIntent(context, eventTime, type));
}
- return intents;
+ return actions;
}
@NonNull
- private static List<Intent> createForFlight(String text) {
- return Arrays.asList(new Intent(Intent.ACTION_WEB_SEARCH)
- .putExtra(SearchManager.QUERY, text));
+ private static List<LabeledIntent> createForFlight(Context context, String text) {
+ return Arrays.asList(new LabeledIntent(
+ context.getString(com.android.internal.R.string.view_flight),
+ context.getString(com.android.internal.R.string.view_flight_desc),
+ new Intent(Intent.ACTION_WEB_SEARCH)
+ .putExtra(SearchManager.QUERY, text)));
}
@NonNull
- private static Intent createCalendarViewIntent(Calendar eventTime) {
+ private static LabeledIntent createCalendarViewIntent(Context context, Calendar eventTime) {
Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
builder.appendPath("time");
ContentUris.appendId(builder, eventTime.getTimeInMillis());
- return new Intent(Intent.ACTION_VIEW).setData(builder.build());
+ return new LabeledIntent(
+ context.getString(com.android.internal.R.string.view_calendar),
+ context.getString(com.android.internal.R.string.view_calendar_desc),
+ new Intent(Intent.ACTION_VIEW).setData(builder.build()));
}
@NonNull
- private static Intent createCalendarCreateEventIntent(
- Calendar eventTime, @EntityType String type) {
+ private static LabeledIntent createCalendarCreateEventIntent(
+ Context context, Calendar eventTime, @EntityType String type) {
final boolean isAllDay = TextClassifier.TYPE_DATE.equals(type);
- return new Intent(Intent.ACTION_INSERT)
- .setData(CalendarContract.Events.CONTENT_URI)
- .putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, isAllDay)
- .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, eventTime.getTimeInMillis())
- .putExtra(CalendarContract.EXTRA_EVENT_END_TIME,
- eventTime.getTimeInMillis() + DEFAULT_EVENT_DURATION);
- }
-
- @Nullable
- public static String getLabel(Context context, @Nullable Intent intent) {
- if (intent == null || intent.getAction() == null) {
- return null;
- }
- final String authority =
- intent.getData() == null ? null : intent.getData().getAuthority();
- switch (intent.getAction()) {
- case Intent.ACTION_DIAL:
- return context.getString(com.android.internal.R.string.dial);
- case Intent.ACTION_SENDTO:
- if ("mailto".equals(intent.getScheme())) {
- return context.getString(com.android.internal.R.string.email);
- } else if ("smsto".equals(intent.getScheme())) {
- return context.getString(com.android.internal.R.string.sms);
- } else {
- return null;
- }
- case Intent.ACTION_INSERT:
- if (CalendarContract.AUTHORITY.equals(authority)) {
- return context.getString(com.android.internal.R.string.add_calendar_event);
- }
- return null;
- case Intent.ACTION_INSERT_OR_EDIT:
- if (ContactsContract.Contacts.CONTENT_ITEM_TYPE.equals(
- intent.getType())) {
- return context.getString(com.android.internal.R.string.add_contact);
- } else {
- return null;
- }
- case Intent.ACTION_VIEW:
- if (CalendarContract.AUTHORITY.equals(authority)) {
- return context.getString(com.android.internal.R.string.view_calendar);
- } else if ("geo".equals(intent.getScheme())) {
- return context.getString(com.android.internal.R.string.map);
- } else if ("http".equals(intent.getScheme())
- || "https".equals(intent.getScheme())) {
- return context.getString(com.android.internal.R.string.browse);
- } else {
- return null;
- }
- case Intent.ACTION_WEB_SEARCH:
- return context.getString(com.android.internal.R.string.view_flight);
- default:
- return null;
- }
+ return new LabeledIntent(
+ context.getString(com.android.internal.R.string.add_calendar_event),
+ context.getString(com.android.internal.R.string.add_calendar_event_desc),
+ new Intent(Intent.ACTION_INSERT)
+ .setData(CalendarContract.Events.CONTENT_URI)
+ .putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, isAllDay)
+ .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME,
+ eventTime.getTimeInMillis())
+ .putExtra(CalendarContract.EXTRA_EVENT_END_TIME,
+ eventTime.getTimeInMillis() + DEFAULT_EVENT_DURATION));
}
}
}
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index d0f9eee..6df1655 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -152,6 +152,14 @@
* will continue to load the resource as usual. Otherwise, the return
* response and data will be used.
*
+ * <p>This callback is invoked for a variety of URL schemes (e.g., {@code http(s):}, {@code
+ * data:}, {@code file:}, etc.), not only those schemes which send requests over the network.
+ * This is not called for {@code javascript:} URLs, {@code blob:} URLs, or for assets accessed
+ * via {@code file:///android_asset/} or {@code file:///android_res/} URLs.
+ *
+ * <p>In the case of redirects, this is only called for the initial resource URL, not any
+ * subsequent redirect URLs.
+ *
* <p class="note"><b>Note:</b> This method is called on a thread
* other than the UI thread so clients should exercise caution
* when accessing private data or the view system.
@@ -182,6 +190,14 @@
* will continue to load the resource as usual. Otherwise, the return
* response and data will be used.
*
+ * <p>This callback is invoked for a variety of URL schemes (e.g., {@code http(s):}, {@code
+ * data:}, {@code file:}, etc.), not only those schemes which send requests over the network.
+ * This is not called for {@code javascript:} URLs, {@code blob:} URLs, or for assets accessed
+ * via {@code file:///android_asset/} or {@code file:///android_res/} URLs.
+ *
+ * <p>In the case of redirects, this is only called for the initial resource URL, not any
+ * subsequent redirect URLs.
+ *
* <p class="note"><b>Note:</b> This method is called on a thread
* other than the UI thread so clients should exercise caution
* when accessing private data or the view system.
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 3775835..92f496a8 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -23,6 +23,7 @@
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
+import android.app.RemoteAction;
import android.content.ClipData;
import android.content.ClipData.Item;
import android.content.Context;
@@ -4045,43 +4046,46 @@
if (textClassification == null) {
return;
}
- final OnClickListener onClick = getSupportedOnClickListener(
- textClassification.getIcon(),
- textClassification.getLabel(),
- textClassification.getIntent());
- if (onClick != null) {
+ if (!textClassification.getActions().isEmpty()) {
+ // Primary assist action (Always shown).
+ final MenuItem item = addAssistMenuItem(menu,
+ textClassification.getActions().get(0), TextView.ID_ASSIST,
+ MENU_ITEM_ORDER_ASSIST, MenuItem.SHOW_AS_ACTION_ALWAYS);
+ item.setIntent(textClassification.getIntent());
+ } else if (hasLegacyAssistItem(textClassification)) {
+ // Legacy primary assist action (Always shown).
final MenuItem item = menu.add(
TextView.ID_ASSIST, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST,
textClassification.getLabel())
.setIcon(textClassification.getIcon())
.setIntent(textClassification.getIntent());
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
- mAssistClickHandlers.put(
- item, TextClassification.createIntentOnClickListener(
- mTextView.getContext(), textClassification.getIntent()));
+ mAssistClickHandlers.put(item, TextClassification.createIntentOnClickListener(
+ TextClassification.createPendingIntent(mTextView.getContext(),
+ textClassification.getIntent())));
}
- final int count = textClassification.getSecondaryActionsCount();
- for (int i = 0; i < count; i++) {
- final OnClickListener onClick1 = getSupportedOnClickListener(
- textClassification.getSecondaryIcon(i),
- textClassification.getSecondaryLabel(i),
- textClassification.getSecondaryIntent(i));
- if (onClick1 == null) {
- continue;
- }
- final int order = MENU_ITEM_ORDER_SECONDARY_ASSIST_ACTIONS_START + i;
- final MenuItem item = menu.add(
- TextView.ID_ASSIST, Menu.NONE, order,
- textClassification.getSecondaryLabel(i))
- .setIcon(textClassification.getSecondaryIcon(i))
- .setIntent(textClassification.getSecondaryIntent(i));
- item.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- mAssistClickHandlers.put(item,
- TextClassification.createIntentOnClickListener(
- mTextView.getContext(), textClassification.getSecondaryIntent(i)));
+ final int count = textClassification.getActions().size();
+ for (int i = 1; i < count; i++) {
+ // Secondary assist action (Never shown).
+ addAssistMenuItem(menu, textClassification.getActions().get(i), Menu.NONE,
+ MENU_ITEM_ORDER_SECONDARY_ASSIST_ACTIONS_START + i - 1,
+ MenuItem.SHOW_AS_ACTION_NEVER);
}
}
+ private MenuItem addAssistMenuItem(Menu menu, RemoteAction action, int intemId, int order,
+ int showAsAction) {
+ final MenuItem item = menu.add(TextView.ID_ASSIST, intemId, order, action.getTitle())
+ .setContentDescription(action.getContentDescription());
+ if (action.shouldShowIcon()) {
+ item.setIcon(action.getIcon().loadDrawable(mTextView.getContext()));
+ }
+ item.setShowAsAction(showAsAction);
+ mAssistClickHandlers.put(item,
+ TextClassification.createIntentOnClickListener(action.getActionIntent()));
+ return item;
+ }
+
private void clearAssistMenuItems(Menu menu) {
int i = 0;
while (i < menu.size()) {
@@ -4094,15 +4098,11 @@
}
}
- @Nullable
- private OnClickListener getSupportedOnClickListener(
- Drawable icon, CharSequence label, Intent intent) {
- final boolean hasUi = icon != null || !TextUtils.isEmpty(label);
- if (hasUi) {
- return TextClassification.createIntentOnClickListener(
- mTextView.getContext(), intent);
- }
- return null;
+ private boolean hasLegacyAssistItem(TextClassification classification) {
+ // Check whether we have the UI data and and action.
+ return (classification.getIcon() != null || !TextUtils.isEmpty(
+ classification.getLabel())) && (classification.getIntent() != null
+ || classification.getOnClickListener() != null);
}
private boolean onAssistMenuItemClicked(MenuItem assistMenuItem) {
@@ -4120,7 +4120,7 @@
final Intent intent = assistMenuItem.getIntent();
if (intent != null) {
onClickListener = TextClassification.createIntentOnClickListener(
- mTextView.getContext(), intent);
+ TextClassification.createPendingIntent(mTextView.getContext(), intent));
}
}
if (onClickListener != null) {
@@ -4824,13 +4824,23 @@
return true;
}
+ private boolean tooLargeTextForMagnifier() {
+ final float magnifierContentHeight = Math.round(
+ mMagnifierAnimator.mMagnifier.getHeight()
+ / mMagnifierAnimator.mMagnifier.getZoom());
+ final Paint.FontMetrics fontMetrics = mTextView.getPaint().getFontMetrics();
+ final float glyphHeight = fontMetrics.descent - fontMetrics.ascent;
+ return glyphHeight > magnifierContentHeight;
+ }
+
protected final void updateMagnifier(@NonNull final MotionEvent event) {
if (mMagnifierAnimator == null) {
return;
}
final PointF showPosInView = new PointF();
- final boolean shouldShow = obtainMagnifierShowCoordinates(event, showPosInView);
+ final boolean shouldShow = !tooLargeTextForMagnifier()
+ && obtainMagnifierShowCoordinates(event, showPosInView);
if (shouldShow) {
// Make the cursor visible and stop blinking.
mRenderCursorRegardlessTiming = true;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7b1acb1..39755aa 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -12474,9 +12474,8 @@
+ " before=" + before + " after=" + after + ": " + buffer);
}
- if (AccessibilityManager.getInstance(mContext).isEnabled()
- && !isPasswordInputType(getInputType()) && !hasPasswordTransformationMethod()) {
- mBeforeText = buffer.toString();
+ if (AccessibilityManager.getInstance(mContext).isEnabled() && (mTransformed != null)) {
+ mBeforeText = mTransformed.toString();
}
TextView.this.sendBeforeTextChanged(buffer, start, before, after);
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 514ff76..03dd77f 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -93,6 +93,7 @@
void noteVibratorOff(int uid);
void noteGpsChanged(in WorkSource oldSource, in WorkSource newSource);
void noteGpsSignalQuality(int signalLevel);
+ void noteUsbConnectionState(boolean connected);
void noteScreenState(int state);
void noteScreenBrightness(int brightness);
void noteUserActivity(int uid, int event);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 3c150c1..8117bf7 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
-import android.app.job.JobProtoEnums;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.UidTraffic;
import android.content.ContentResolver;
@@ -767,6 +766,8 @@
int mCameraOnNesting;
StopwatchTimer mCameraOnTimer;
+ int mUsbDataState; // 0: unknown, 1: disconnected, 2: connected
+
int mGpsSignalQualityBin = -1;
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
protected final StopwatchTimer[] mGpsSignalQualityTimer =
@@ -5240,6 +5241,19 @@
}
}
+ public void noteUsbConnectionStateLocked(boolean connected) {
+ int newState = connected ? 2 : 1;
+ if (mUsbDataState != newState) {
+ mUsbDataState = newState;
+ if (connected) {
+ mHistoryCur.states2 |= HistoryItem.STATE2_USB_DATA_LINK_FLAG;
+ } else {
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG;
+ }
+ addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+ }
+
void stopAllPhoneSignalStrengthTimersLocked(int except) {
final long elapsedRealtime = mClocks.elapsedRealtime();
for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -5999,7 +6013,6 @@
if (strengthBin >= 0) {
if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
- StatsLog.write(StatsLog.WIFI_SIGNAL_STRENGTH_CHANGED, strengthBin);
}
mHistoryCur.states2 =
(mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
@@ -6010,6 +6023,7 @@
} else {
stopAllWifiSignalStrengthTimersLocked(-1);
}
+ StatsLog.write(StatsLog.WIFI_SIGNAL_STRENGTH_CHANGED, strengthBin);
mWifiSignalStrengthBin = strengthBin;
}
}
@@ -7250,25 +7264,17 @@
public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
- StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, getUid(), null,
- StatsLog.AUDIO_STATE_CHANGED__STATE__ON);
}
public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
if (mAudioTurnedOnTimer != null) {
mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
- if (!mAudioTurnedOnTimer.isRunningLocked()) { // only tell statsd if truly stopped
- StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, getUid(), null,
- StatsLog.AUDIO_STATE_CHANGED__STATE__OFF);
- }
}
}
public void noteResetAudioLocked(long elapsedRealtimeMs) {
if (mAudioTurnedOnTimer != null) {
mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
- StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, getUid(), null,
- StatsLog.AUDIO_STATE_CHANGED__STATE__OFF);
}
}
@@ -7282,25 +7288,17 @@
public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
- StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(), null,
- StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED__STATE__ON);
}
public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
if (mVideoTurnedOnTimer != null) {
mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
- if (!mVideoTurnedOnTimer.isRunningLocked()) { // only tell statsd if truly stopped
- StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(),
- null, StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED__STATE__OFF);
- }
}
}
public void noteResetVideoLocked(long elapsedRealtimeMs) {
if (mVideoTurnedOnTimer != null) {
mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
- StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(), null,
- StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED__STATE__OFF);
}
}
@@ -7314,25 +7312,17 @@
public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
- StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), null,
- StatsLog.FLASHLIGHT_STATE_CHANGED__STATE__ON);
}
public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
if (mFlashlightTurnedOnTimer != null) {
mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
- if (!mFlashlightTurnedOnTimer.isRunningLocked()) {
- StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), null,
- StatsLog.FLASHLIGHT_STATE_CHANGED__STATE__OFF);
- }
}
}
public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
if (mFlashlightTurnedOnTimer != null) {
mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
- StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), null,
- StatsLog.FLASHLIGHT_STATE_CHANGED__STATE__OFF);
}
}
@@ -7346,25 +7336,17 @@
public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
- StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, getUid(), null,
- StatsLog.CAMERA_STATE_CHANGED__STATE__ON);
}
public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
if (mCameraTurnedOnTimer != null) {
mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
- if (!mCameraTurnedOnTimer.isRunningLocked()) { // only tell statsd if truly stopped
- StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, getUid(), null,
- StatsLog.CAMERA_STATE_CHANGED__STATE__OFF);
- }
}
}
public void noteResetCameraLocked(long elapsedRealtimeMs) {
if (mCameraTurnedOnTimer != null) {
mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
- StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, getUid(), null,
- StatsLog.CAMERA_STATE_CHANGED__STATE__OFF);
}
}
@@ -10040,8 +10022,6 @@
DualTimer t = mSyncStats.startObject(name);
if (t != null) {
t.startRunningLocked(elapsedRealtimeMs);
- StatsLog.write_non_chained(StatsLog.SYNC_STATE_CHANGED, getUid(), null, name,
- StatsLog.SYNC_STATE_CHANGED__STATE__ON);
}
}
@@ -10049,10 +10029,6 @@
DualTimer t = mSyncStats.stopObject(name);
if (t != null) {
t.stopRunningLocked(elapsedRealtimeMs);
- if (!t.isRunningLocked()) { // only tell statsd if truly stopped
- StatsLog.write_non_chained(StatsLog.SYNC_STATE_CHANGED, getUid(), null, name,
- StatsLog.SYNC_STATE_CHANGED__STATE__OFF);
- }
}
}
@@ -10060,9 +10036,6 @@
DualTimer t = mJobStats.startObject(name);
if (t != null) {
t.startRunningLocked(elapsedRealtimeMs);
- StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED, getUid(), null,
- name, StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__STARTED,
- JobProtoEnums.STOP_REASON_CANCELLED);
}
}
@@ -10070,11 +10043,6 @@
DualTimer t = mJobStats.stopObject(name);
if (t != null) {
t.stopRunningLocked(elapsedRealtimeMs);
- if (!t.isRunningLocked()) { // only tell statsd if truly stopped
- StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED, getUid(), null,
- name, StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__FINISHED,
- stopReason);
- }
}
if (mBsi.mOnBatteryTimeBase.isRunning()) {
SparseIntArray types = mJobCompletions.get(name);
@@ -10182,10 +10150,6 @@
public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
t.startRunningLocked(elapsedRealtimeMs);
- if (sensor != Sensor.GPS) {
- StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, getUid(), null, sensor,
- StatsLog.SENSOR_STATE_CHANGED__STATE__ON);
- }
}
public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
@@ -10193,10 +10157,6 @@
DualTimer t = getSensorTimerLocked(sensor, false);
if (t != null) {
t.stopRunningLocked(elapsedRealtimeMs);
- if (sensor != Sensor.GPS) {
- StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, getUid(), null,
- sensor, StatsLog.SENSOR_STATE_CHANGED__STATE__OFF);
- }
}
}
diff --git a/core/java/com/android/internal/os/RoSystemProperties.java b/core/java/com/android/internal/os/RoSystemProperties.java
index 89a4e17..dc660a4 100644
--- a/core/java/com/android/internal/os/RoSystemProperties.java
+++ b/core/java/com/android/internal/os/RoSystemProperties.java
@@ -31,6 +31,8 @@
SystemProperties.get("ro.control_privapp_permissions");
// ------ ro.config.* -------- //
+ public static final boolean CONFIG_AVOID_GFX_ACCEL =
+ SystemProperties.getBoolean("ro.config.avoid_gfx_accel", false);
public static final boolean CONFIG_LOW_RAM =
SystemProperties.getBoolean("ro.config.low_ram", false);
public static final boolean CONFIG_SMALL_BATTERY =
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 221bf88..ad5743d 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -18,7 +18,7 @@
import android.content.ComponentName;
import android.graphics.Rect;
-import android.hardware.fingerprint.IFingerprintDialogReceiver;
+import android.hardware.biometrics.IBiometricDialogReceiver;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
@@ -141,7 +141,7 @@
void showShutdownUi(boolean isReboot, String reason);
// Used to show the dialog when FingerprintService starts authentication
- void showFingerprintDialog(in Bundle bundle, IFingerprintDialogReceiver receiver);
+ void showFingerprintDialog(in Bundle bundle, IBiometricDialogReceiver receiver);
// Used to hide the dialog when a finger is authenticated
void onFingerprintAuthenticated();
// Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index adf4287..0c5efe2 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -20,7 +20,7 @@
import android.graphics.Rect;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
-import android.hardware.fingerprint.IFingerprintDialogReceiver;
+import android.hardware.biometrics.IBiometricDialogReceiver;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
@@ -88,7 +88,7 @@
void showPinningEscapeToast();
// Used to show the dialog when FingerprintService starts authentication
- void showFingerprintDialog(in Bundle bundle, IFingerprintDialogReceiver receiver);
+ void showFingerprintDialog(in Bundle bundle, IBiometricDialogReceiver receiver);
// Used to hide the dialog when a finger is authenticated
void onFingerprintAuthenticated();
// Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index c71e505..c5be8e4 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -142,12 +142,24 @@
// Package names that are exempted from private API blacklisting
final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>();
+ // The list of carrier applications which should be disabled until used.
+ // This function suppresses update notifications for these pre-installed apps.
+ // In SubscriptionInfoUpdater, the listed applications are disabled until used when all of the
+ // following conditions are met.
+ // 1. Not currently carrier-privileged according to the inserted SIM
+ // 2. Pre-installed
+ // 3. In the default state (enabled but not explicitly)
+ // And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted
+ // that marks the app as carrier privileged. It also grants the app default permissions
+ // for Phone and Location. As such, apps MUST only ever be added to this list if they
+ // obtain user consent to access their location through other means.
+ final ArraySet<String> mDisabledUntilUsedPreinstalledCarrierApps = new ArraySet<>();
+
// These are the packages of carrier-associated apps which should be disabled until used until
// a SIM is inserted which grants carrier privileges to that carrier app.
final ArrayMap<String, List<String>> mDisabledUntilUsedPreinstalledCarrierAssociatedApps =
new ArrayMap<>();
-
final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>();
final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>();
@@ -232,6 +244,10 @@
return mBackupTransportWhitelist;
}
+ public ArraySet<String> getDisabledUntilUsedPreinstalledCarrierApps() {
+ return mDisabledUntilUsedPreinstalledCarrierApps;
+ }
+
public ArrayMap<String, List<String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() {
return mDisabledUntilUsedPreinstalledCarrierAssociatedApps;
}
@@ -630,6 +646,18 @@
associatedPkgs.add(pkgname);
}
XmlUtils.skipCurrentTag(parser);
+ } else if ("disabled-until-used-preinstalled-carrier-app".equals(name)
+ && allowAppConfigs) {
+ String pkgname = parser.getAttributeValue(null, "package");
+ if (pkgname == null) {
+ Slog.w(TAG,
+ "<disabled-until-used-preinstalled-carrier-app> without "
+ + "package in " + permFile + " at "
+ + parser.getPositionDescription());
+ } else {
+ mDisabledUntilUsedPreinstalledCarrierApps.add(pkgname);
+ }
+ XmlUtils.skipCurrentTag(parser);
} else if ("privapp-permissions".equals(name) && allowPrivappPermissions) {
// privapp permissions from system, vendor and product partitions are stored
// separately. This is to prevent xml files in the vendor partition from
diff --git a/core/proto/android/app/job/enums.proto b/core/proto/android/app/job/enums.proto
index 0f14f20..17bf4fb 100644
--- a/core/proto/android/app/job/enums.proto
+++ b/core/proto/android/app/job/enums.proto
@@ -24,6 +24,7 @@
// Reasons a job is stopped.
// Primarily used in android.app.job.JobParameters.java.
enum StopReasonEnum {
+ STOP_REASON_UNKNOWN = -1;
STOP_REASON_CANCELLED = 0;
STOP_REASON_CONSTRAINTS_NOT_SATISFIED = 1;
STOP_REASON_PREEMPT = 2;
diff --git a/core/proto/android/content/clipdata.proto b/core/proto/android/content/clipdata.proto
index aeeef97..cbc00a7 100644
--- a/core/proto/android/content/clipdata.proto
+++ b/core/proto/android/content/clipdata.proto
@@ -25,7 +25,7 @@
// An android.content.ClipData object.
message ClipDataProto {
- option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+ option (.android.msg_privacy).dest = DEST_LOCAL;
optional android.content.ClipDescriptionProto description = 1;
@@ -40,7 +40,7 @@
// An android.content.ClipData.Item object.
message Item {
- option (.android.msg_privacy).dest = DEST_EXPLICIT;
+ option (.android.msg_privacy).dest = DEST_LOCAL;
oneof data {
string html_text = 1;
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index 7f8bed5..76a3b5d 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -20,8 +20,9 @@
option java_multiple_files = true;
option java_outer_classname = "SettingsServiceProto";
-import "frameworks/base/core/proto/android/providers/settings/common.proto";
import "frameworks/base/core/proto/android/providers/settings/global.proto";
+import "frameworks/base/core/proto/android/providers/settings/secure.proto";
+import "frameworks/base/core/proto/android/providers/settings/system.proto";
import "frameworks/base/libs/incident/proto/android/privacy.proto";
message SettingsServiceDumpProto {
@@ -47,351 +48,6 @@
optional SystemSettingsProto system_settings = 3;
}
-// Note: it's a conscious decision to add each setting as a separate field. This
-// allows annotating each setting with its own privacy tag.
-message SecureSettingsProto {
- option (android.msg_privacy).dest = DEST_EXPLICIT;
-
- repeated SettingsOperationProto historical_operations = 1;
-
- optional SettingProto android_id = 2;
- optional SettingProto default_input_method = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto selected_input_method_subtype = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto input_methods_subtype_history = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto input_method_selector_visibility = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // The currently selected voice interaction service flattened ComponentName.
- optional SettingProto voice_interaction_service = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // The currently selected autofill service flattened ComponentName.
- optional SettingProto autofill_service = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Boolean indicating if Autofill supports field classification.
- optional SettingProto autofill_feature_field_classification = 9 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto autofill_user_data_max_user_data_size = 10 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto autofill_user_data_max_field_classification_ids_size = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto autofill_user_data_max_category_count = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto autofill_user_data_max_value_length = 13 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto autofill_user_data_min_value_length = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto user_setup_complete = 15 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Whether the current user has been set up via setup wizard (0 = false,
- // 1 = true). This value differs from USER_SETUP_COMPLETE in that it can be
- // reset back to 0 in case SetupWizard has been re-enabled on TV devices.
- optional SettingProto tv_user_setup_complete = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
- repeated SettingProto completed_categories = 17;
- optional SettingProto enabled_input_methods = 18 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto disabled_system_input_methods = 19 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto show_ime_with_hard_keyboard = 20 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto always_on_vpn_app = 21;
- optional SettingProto always_on_vpn_lockdown = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto install_non_market_apps = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto unknown_sources_default_reversed = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // The degree of location access enabled by the user.
- optional SettingProto location_mode = 25 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // The App or module that changes the location mode.
- optional SettingProto location_changer = 26 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Whether lock-to-app will lock the keyguard when exiting.
- optional SettingProto lock_to_app_exit_locked = 27 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto lock_screen_lock_after_timeout = 28 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto lock_screen_allow_private_notifications = 29 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto lock_screen_allow_remote_input = 30 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto show_note_about_notification_hiding = 31 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto trust_agents_initialized = 32 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto parental_control_enabled = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto parental_control_last_update = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto parental_control_redirect_url = 35 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto settings_classname = 36 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_enabled = 37 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_shortcut_enabled = 38 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_shortcut_on_lock_screen = 39 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_shortcut_dialog_shown = 40 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_shortcut_target_service = 41 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Setting specifying the accessibility service or feature to be toggled via
- // the accessibility button in the navigation bar. This is either a
- // flattened ComponentName or the class name of a system class implementing
- // a supported accessibility feature.
- optional SettingProto accessibility_button_target_component = 42 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto touch_exploration_enabled = 43 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // List of the enabled accessibility providers.
- optional SettingProto enabled_accessibility_services = 44;
- // List of the accessibility services to which the user has granted
- // permission to put the device into touch exploration mode.
- optional SettingProto touch_exploration_granted_accessibility_services = 45;
- // Uri of the slice that's presented on the keyguard. Defaults to a slice
- // with the date and next alarm.
- optional SettingProto keyguard_slice_uri = 46;
- // Whether to speak passwords while in accessibility mode.
- optional SettingProto accessibility_speak_password = 47 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_high_text_contrast_enabled = 48 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_display_magnification_enabled = 49 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_display_magnification_navbar_enabled = 50 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_display_magnification_scale = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_soft_keyboard_mode = 52 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_captioning_enabled = 53 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_captioning_locale = 54 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_captioning_preset = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_captioning_background_color = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_captioning_foreground_color = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_captioning_edge_type = 58 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_captioning_edge_color = 59 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_captioning_window_color = 60 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_captioning_typeface = 61 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_captioning_font_scale = 62 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_display_inversion_enabled = 63 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_display_daltonizer_enabled = 64 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Integer property that specifies the type of color space adjustment to perform.
- optional SettingProto accessibility_display_daltonizer = 65 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_autoclick_enabled = 66 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_autoclick_delay = 67 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_large_pointer_icon = 68 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto long_press_timeout = 69 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto multi_press_timeout = 70 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto enabled_print_services = 71;
- optional SettingProto disabled_print_services = 72;
- optional SettingProto display_density_forced = 73 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto tts_default_rate = 74 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto tts_default_pitch = 75 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto tts_default_synth = 76 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto tts_default_locale = 77 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto tts_enabled_plugins = 78;
- optional SettingProto connectivity_release_pending_intent_delay_ms = 79 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto allowed_geolocation_origins = 80;
- optional SettingProto preferred_tty_mode = 81 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto enhanced_voice_privacy_enabled = 82 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto tty_mode_enabled = 83 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto backup_enabled = 84 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto backup_auto_restore = 85 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto backup_provisioned = 86 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto backup_transport = 87 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto last_setup_shown = 88 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_global_search_activity = 89 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_num_promoted_sources = 90 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_max_results_to_display = 91 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_max_results_per_source = 92 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_web_results_override_limit = 93 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_promoted_source_deadline_millis = 94 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_source_timeout_millis = 95 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_prefill_millis = 96 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_max_stat_age_millis = 97 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_max_source_event_age_millis = 98 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_min_impressions_for_source_ranking = 99 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_min_clicks_for_source_ranking = 100 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_max_shortcuts_returned = 101 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_query_thread_core_pool_size = 102 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_query_thread_max_pool_size = 103 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_shortcut_refresh_core_pool_size = 104 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_shortcut_refresh_max_pool_size = 105 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_thread_keepalive_seconds = 106 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto search_per_source_concurrent_query_limit = 107 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Whether or not alert sounds are played on StorageManagerService events.
- optional SettingProto mount_play_notification_snd = 108 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto mount_ums_autostart = 109 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto mount_ums_prompt = 110 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto mount_ums_notify_enabled = 111 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto anr_show_background = 112 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto show_first_crash_dialog_dev_option = 113 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // The ComponentName string of the service to be used as the voice
- // recognition service.
- optional SettingProto voice_recognition_service = 114 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto package_verifier_user_consent = 115 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto selected_spell_checker = 116 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto selected_spell_checker_subtype = 117 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto spell_checker_enabled = 118 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto incall_power_button_behavior = 119 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto incall_back_button_behavior = 120 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto wake_gesture_enabled = 121 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto doze_enabled = 122 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto doze_always_on = 123 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto doze_pulse_on_pick_up = 124 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto doze_pulse_on_long_press = 125 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto doze_pulse_on_double_tap = 126 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto ui_night_mode = 127 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto screensaver_enabled = 128 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto screensaver_components = 129 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto screensaver_activate_on_dock = 130 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto screensaver_activate_on_sleep = 131 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto screensaver_default_component = 132 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto nfc_payment_default_component = 133 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto nfc_payment_foreground = 134 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto sms_default_application = 135 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto dialer_default_application = 136 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto emergency_assistance_application = 137 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto assist_structure_enabled = 138 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto assist_screenshot_enabled = 139 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto assist_disclosure_enabled = 140 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto show_rotation_suggestions = 141 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto num_rotation_suggestions_accepted = 142 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Read only list of the service components that the current user has
- // explicitly allowed to see and assist with all of the user's
- // notifications.
- optional SettingProto enabled_notification_assistant = 143 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto enabled_notification_listeners = 144 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto enabled_notification_policy_access_packages = 145 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Defines whether managed profile ringtones should be synced from its
- // parent profile.
- optional SettingProto sync_parent_sounds = 146 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto immersive_mode_confirmations = 147 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // The query URI to find a print service to install.
- optional SettingProto print_service_search_uri = 148 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // The query URI to find an NFC service to install.
- optional SettingProto payment_service_search_uri = 149 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // The query URI to find an auto fill service to install.
- optional SettingProto autofill_service_search_uri = 150 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto skip_first_use_hints = 151 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto unsafe_volume_music_active_ms = 152 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto lock_screen_show_notifications = 153 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto tv_input_hidden_inputs = 154;
- optional SettingProto tv_input_custom_labels = 155;
- optional SettingProto usb_audio_automatic_routing_disabled = 156 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto sleep_timeout = 157 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto double_tap_to_wake = 158 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // The current assistant component. It could be a voice interaction service,
- // or an activity that handles ACTION_ASSIST, or empty, which means using
- // the default handling.
- optional SettingProto assistant = 159 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto camera_gesture_disabled = 160 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto camera_double_tap_power_gesture_disabled = 161 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto camera_double_twist_to_flip_enabled = 162 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto camera_lift_trigger_enabled = 163 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto assist_gesture_enabled = 164 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto assist_gesture_sensitivity = 165 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto assist_gesture_silence_alerts_enabled = 166 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto assist_gesture_wake_enabled = 167 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto assist_gesture_setup_complete = 168 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto night_display_activated = 169 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto night_display_auto_mode = 170 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto night_display_color_temperature = 171 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto night_display_custom_start_time = 172 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto night_display_custom_end_time = 173 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto night_display_last_activated_time = 174 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto enabled_vr_listeners = 175 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto vr_display_mode = 176 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto carrier_apps_handled = 177 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto managed_profile_contact_remote_search = 178 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto automatic_storage_manager_enabled = 179 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto automatic_storage_manager_days_to_retain = 180 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto automatic_storage_manager_bytes_cleared = 181 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto automatic_storage_manager_last_run = 182 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto automatic_storage_manager_turned_off_by_policy = 183 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto system_navigation_keys_enabled = 184 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Holds comma-separated list of ordering of QuickSettings tiles.
- optional SettingProto qs_tiles = 185 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto instant_apps_enabled = 186 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto device_paired = 187 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto package_verifier_state = 188 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto cmas_additional_broadcast_pkg = 189 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto notification_badging = 190 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto qs_auto_added_tiles = 191 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto lockdown_in_power_menu = 192 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto backup_manager_constants = 193;
- optional SettingProto backup_local_transport_parameters = 194;
- optional SettingProto bluetooth_on_while_driving = 195 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingsProto volume_hush_gesture = 196 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Please insert fields in the same order as in
- // frameworks/base/core/java/android/provider/Settings.java.
- // Next tag = 197
-}
-
-message SystemSettingsProto {
- option (android.msg_privacy).dest = DEST_EXPLICIT;
-
- repeated SettingsOperationProto historical_operations = 1;
-
- optional SettingProto end_button_behavior = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto advanced_settings = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto bluetooth_discoverability = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto bluetooth_discoverability_timeout = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto font_scale = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto system_locales = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto display_color_mode = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto screen_off_timeout = 9 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto screen_brightness = 10 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto screen_brightness_for_vr = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto screen_brightness_mode = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto screen_auto_brightness_adj = 13 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Determines which streams are affected by ringer mode changes. The stream
- // type's bit will be set to 1 if it should be muted when going into an
- // inaudible ringer mode.
- optional SettingProto mode_ringer_streams_affected = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto mute_streams_affected = 15 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto vibrate_on = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto vibrate_input_devices = 17 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto notification_vibration_intensity = 18 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto haptic_feedback_intensity = 19 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto volume_ring = 20 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto volume_system = 21 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto volume_voice = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto volume_music = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto volume_alarm = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto volume_notification = 25 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto volume_bluetooth_sco = 26 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto volume_accessibility = 27 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto volume_master = 28 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto master_mono = 29 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Whether silent mode should allow vibration feedback. This is used
- // internally in AudioService and the Sound settings activity to coordinate
- // decoupling of vibrate and silent modes. This setting will likely be
- // removed in a future release with support for audio/vibe feedback
- // profiles.
- // Not used anymore. On devices with vibrator, the user explicitly selects
- // silent or vibrate mode. Kept for use by legacy database upgrade code in
- // DatabaseHelper.
- optional SettingProto vibrate_in_silent = 30 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Appended to various volume related settings to record the previous values
- // before the settings were affected by a silent/vibrate ringer mode change.
- optional SettingProto append_for_last_audible = 31 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto ringtone = 32;
- optional SettingProto ringtone_cache = 33;
- optional SettingProto notification_sound = 34;
- optional SettingProto notification_sound_cache = 35;
- optional SettingProto alarm_alert = 36;
- optional SettingProto alarm_alert_cache = 37;
- optional SettingProto media_button_receiver = 38;
- optional SettingProto text_auto_replace = 39 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto text_auto_caps = 40 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto text_auto_punctuate = 41 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto text_show_password = 42 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto show_gtalk_service_status = 43 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto time_12_24 = 44 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto date_format = 45 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto setup_wizard_has_run = 46 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accelerometer_rotation = 47 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto user_rotation = 48 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto hide_rotation_lock_toggle_for_accessibility = 49 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto vibrate_when_ringing = 50 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto dtmf_tone_when_dialing = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto dtmf_tone_type_when_dialing = 52 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto hearing_aid = 53 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto tty_mode = 54 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // User-selected RTT mode. When on, outgoing and incoming calls will be
- // answered as RTT calls when supported by the device and carrier. Boolean
- // value.
- optional SettingProto rtt_calling_mode = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto sound_effects_enabled = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto haptic_feedback_enabled = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto notification_light_pulse = 58 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Show pointer location on screen? 0 = no, 1 = yes.
- optional SettingProto pointer_location = 59 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto show_touches = 60 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Log raw orientation data from {@link
- // com.android.server.policy.WindowOrientationListener} for use with the
- // orientationplot.py tool.
- // 0 = no, 1 = yes
- optional SettingProto window_orientation_listener_log = 61 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto lockscreen_sounds_enabled = 62 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto lockscreen_disabled = 63 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto sip_receive_calls = 64 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto sip_call_options = 65 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto sip_always = 66 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto sip_address_only = 67 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto pointer_speed = 68 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto lock_to_app_enabled = 69 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto egg_mode = 70 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto show_battery_percent = 71 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto when_to_make_wifi_calls = 72 [ (android.privacy).dest = DEST_AUTOMATIC ];
-
- // Please insert fields in the same order as in
- // frameworks/base/core/java/android/provider/Settings.java.
- // Next tag = 73;
-}
-
message SettingsProto {
// Enum values gotten from Settings.java
enum ScreenBrightnessMode {
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
new file mode 100644
index 0000000..cfb8980
--- /dev/null
+++ b/core/proto/android/providers/settings/secure.proto
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.providers.settings;
+
+option java_multiple_files = true;
+
+import "frameworks/base/core/proto/android/providers/settings/common.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
+// Note: it's a conscious decision to add each setting as a separate field. This
+// allows annotating each setting with its own privacy tag.
+message SecureSettingsProto {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ repeated SettingsOperationProto historical_operations = 1;
+
+ message Accessibility {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // List of the enabled accessibility providers.
+ optional SettingProto enabled_accessibility_services = 2;
+ optional SettingProto autoclick_enabled = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto autoclick_delay = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Setting specifying the accessibility service or feature to be toggled via
+ // the accessibility button in the navigation bar. This is either a
+ // flattened ComponentName or the class name of a system class implementing
+ // a supported accessibility feature.
+ optional SettingProto button_target_component = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto captioning_enabled = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto captioning_locale = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto captioning_preset = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto captioning_background_color = 9 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto captioning_foreground_color = 10 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto captioning_edge_type = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto captioning_edge_color = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto captioning_window_color = 13 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto captioning_typeface = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto captioning_font_scale = 15 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto display_daltonizer_enabled = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Integer property that specifies the type of color space adjustment to perform.
+ optional SettingProto display_daltonizer = 17 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto display_inversion_enabled = 18 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto display_magnification_enabled = 19 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto display_magnification_navbar_enabled = 20 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto display_magnification_scale = 21 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto high_text_contrast_enabled = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto large_pointer_icon = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto shortcut_enabled = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto shortcut_on_lock_screen = 25 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto shortcut_dialog_shown = 26 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto shortcut_target_service = 27 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto soft_keyboard_mode = 28 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Whether to speak passwords while in accessibility mode.
+ optional SettingProto speak_password = 29 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto touch_exploration_enabled = 30 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // List of the accessibility services to which the user has granted
+ // permission to put the device into touch exploration mode.
+ optional SettingProto touch_exploration_granted_accessibility_services = 31;
+ }
+ optional Accessibility accessibility = 2;
+
+ // Origins for which browsers should allow geolocation by default.
+ // The value is a space-separated list of origins.
+ optional SettingProto allowed_geolocation_origins = 3;
+
+ message AlwaysOnVpn {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto app = 1;
+ optional SettingProto lockdown = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional AlwaysOnVpn always_on_vpn = 4;
+
+ optional SettingProto android_id = 5;
+ optional SettingProto anr_show_background = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Assist {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // The current assistant component. It could be a voice interaction service,
+ // or an activity that handles ACTION_ASSIST, or empty, which means using
+ // the default handling.
+ optional SettingProto assistant = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto structure_enabled = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto screenshot_enabled = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto disclosure_enabled = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto gesture_enabled = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto gesture_sensitivity = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto gesture_silence_alerts_enabled = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto gesture_wake_enabled = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto gesture_setup_complete = 9 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Assist assist = 7;
+
+ message Autofill {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // The currently selected autofill service flattened ComponentName.
+ optional SettingProto service = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Boolean indicating if Autofill supports field classification.
+ optional SettingProto feature_field_classification = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto user_data_max_user_data_size = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto user_data_max_field_classification_ids_size = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto user_data_max_category_count = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto user_data_max_value_length = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto user_data_min_value_length = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // The query URI to find an auto fill service to install.
+ optional SettingProto service_search_uri = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Autofill autofill = 8;
+
+ message AutomaticStorageManager {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto days_to_retain = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bytes_cleared = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto last_run = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto turned_off_by_policy = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional AutomaticStorageManager automatic_storage_manager = 9;
+
+ message Backup {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto auto_restore = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto provisioned = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto transport = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto manager_constants = 5;
+ optional SettingProto local_transport_parameters = 6;
+ }
+ optional Backup backup = 10;
+
+ optional SettingProto bluetooth_on_while_driving = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Camera {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto gesture_disabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto double_tap_power_gesture_disabled = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto double_twist_to_flip_enabled = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto lift_trigger_enabled = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Camera camera = 12;
+
+ optional SettingProto carrier_apps_handled = 13 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto cmas_additional_broadcast_pkg = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ repeated SettingProto completed_categories = 15;
+ optional SettingProto connectivity_release_pending_intent_delay_ms = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto device_paired = 17 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dialer_default_application = 18 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto display_density_forced = 19 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto double_tap_to_wake = 20 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Doze {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto always_on = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto pulse_on_pick_up = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto pulse_on_long_press = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto pulse_on_double_tap = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Doze doze = 21;
+
+ optional SettingProto emergency_assistance_application = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enhanced_voice_privacy_enabled = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto immersive_mode_confirmations = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Incall {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto power_button_behavior = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto back_button_behavior = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Incall incall = 25;
+
+ message InputMethods {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto default_input_method = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto disabled_system_input_methods = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enabled_input_methods = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto method_selector_visibility = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto subtype_history = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto selected_input_method_subtype = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_ime_with_hard_keyboard = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional InputMethods input_methods = 26;
+
+ optional SettingProto install_non_market_apps = 27 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto instant_apps_enabled = 28 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Uri of the slice that's presented on the keyguard. Defaults to a slice
+ // with the date and next alarm.
+ optional SettingProto keyguard_slice_uri = 29;
+ optional SettingProto last_setup_shown = 30 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Location {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // The degree of location access enabled by the user.
+ optional SettingProto mode = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // The App or module that changes the location mode.
+ optional SettingProto changer = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Location location = 31;
+
+ message LockScreen {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto lock_after_timeout = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto allow_private_notifications = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto allow_remote_input = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_notifications = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional LockScreen lock_screen = 32;
+
+ // Whether lock-to-app will lock the keyguard when exiting.
+ optional SettingProto lock_to_app_exit_locked = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto lockdown_in_power_menu = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto long_press_timeout = 35 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message ManagedProfile {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto contact_remote_search = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional ManagedProfile managed_profile = 36;
+
+ message Mount {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // Whether or not alert sounds are played on StorageManagerService events.
+ optional SettingProto play_notification_snd = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto ums_autostart = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto ums_prompt = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto ums_notify_enabled = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Mount mount = 37;
+
+ optional SettingProto multi_press_timeout = 38 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message NfcPayment {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto default_component = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Whether NFC payment is handled by the foreground application or a default.
+ optional SettingProto foreground = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // The query URI to find an NFC service to install.
+ optional SettingProto payment_service_search_uri = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional NfcPayment nfc_payment = 39;
+
+ message NightDisplay {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto activated = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto auto_mode = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto color_temperature = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto custom_start_time = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto custom_end_time = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto last_activated_time = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional NightDisplay night_display = 40;
+
+ message Notification {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // Read only list of the service components that the current user has
+ // explicitly allowed to see and assist with all of the user's
+ // notifications.
+ // "enabled_notification_assistant" in code.
+ optional SettingProto enabled_assistant = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enabled_listeners = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enabled_policy_access_packages = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto badging = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_note_about_notification_hiding = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Notification notification = 41;
+
+ message PackageVerifier {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto user_consent = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto state = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional PackageVerifier package_verifier = 42;
+
+ message ParentalControl {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto last_update = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto redirect_url = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional ParentalControl parental_control = 43;
+
+ message PrintService {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // The query URI to find a print service to install.
+ optional SettingProto search_uri = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto disabled_print_services = 2;
+ optional SettingProto enabled_print_services = 3;
+ }
+ optional PrintService print_service = 44;
+
+ message QuickSettings {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // Holds comma-separated list of ordering of QuickSettings tiles.
+ optional SettingProto tiles = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto auto_added_tiles = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional QuickSettings qs = 45;
+
+ message Rotation {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto show_rotation_suggestions = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto num_rotation_suggestions_accepted = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Rotation rotation = 46;
+
+ message Screensaver {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto components = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto activate_on_dock = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto activate_on_sleep = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto default_component = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Screensaver screensaver = 47;
+
+ message Search {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto global_search_activity = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto num_promoted_sources = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto max_results_to_display = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto max_results_per_source = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto web_results_override_limit = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto promoted_source_deadline_millis = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto source_timeout_millis = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto prefill_millis = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto max_stat_age_millis = 9 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto max_source_event_age_millis = 10 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto min_impressions_for_source_ranking = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto min_clicks_for_source_ranking = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto max_shortcuts_returned = 13 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto query_thread_core_pool_size = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto query_thread_max_pool_size = 15 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto shortcut_refresh_core_pool_size = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto shortcut_refresh_max_pool_size = 17 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto thread_keepalive_seconds = 18 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto per_source_concurrent_query_limit = 19 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Search search = 48;
+
+ message SpellChecker {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // "selected_spell_checker" in code.
+ optional SettingProto selected = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // "selected_spell_checker_subtype" in code.
+ optional SettingProto selected_subtype = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional SpellChecker spell_checker = 49;
+
+ optional SettingProto settings_classname = 50 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_first_crash_dialog_dev_option = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto skip_first_use_hints = 52 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sleep_timeout = 53 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sms_default_application = 54 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Defines whether managed profile ringtones should be synced from its
+ // parent profile.
+ optional SettingProto sync_parent_sounds = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto system_navigation_keys_enabled = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto trust_agents_initialized = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Tts {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto default_rate = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto default_pitch = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto default_synth = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto default_locale = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enabled_plugins = 5;
+ }
+ optional Tts tts = 58;
+
+ message Tty {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto tty_mode_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // The preferred TTY mode:
+ // 0 = TTy Off, CDMA default
+ // 1 = TTY Full
+ // 2 = TTY HCO
+ // 3 = TTY VCO
+ optional SettingProto preferred_tty_mode = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Tty tty = 59;
+
+ message Tv {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // Whether the current user has been set up via setup wizard (0 = false,
+ // 1 = true). This value differs from USER_SETUP_COMPLETE in that it can be
+ // reset back to 0 in case SetupWizard has been re-enabled on TV devices.
+ optional SettingProto user_setup_complete = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto input_hidden_inputs = 2;
+ optional SettingProto input_custom_labels = 3;
+ }
+ optional Tv tv = 60;
+
+ optional SettingProto ui_night_mode = 61 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto unknown_sources_default_reversed = 62 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto usb_audio_automatic_routing_disabled = 63 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Whether the current user has been set up via setup wizard (0 = false, 1 = true)
+ optional SettingProto user_setup_complete = 64 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Voice {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // The currently selected voice interaction service flattened ComponentName.
+ optional SettingProto interaction_service = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // The ComponentName string of the service to be used as the voice
+ // recognition service.
+ optional SettingProto recognition_service = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Voice voice = 65;
+
+ message Volume {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // What behavior should be invoked when the volume hush gesture is triggered
+ // One of VOLUME_HUSH_OFF, VOLUME_HUSH_VIBRATE, VOLUME_HUSH_MUTE.
+ optional SettingProto hush_gesture = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Persisted playback time after a user confirmation of an unsafe volume level.
+ optional SettingProto unsafe_volume_music_active_ms = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Volume volume = 66;
+
+ message Vr {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto display_mode = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enabled_listeners = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Vr vr = 67;
+
+ optional SettingProto wake_gesture_enabled = 68 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ // Please insert fields in alphabetical order and group them into messages
+ // if possible (to avoid reaching the method limit).
+ // Next tag = 69;
+}
diff --git a/core/proto/android/providers/settings/system.proto b/core/proto/android/providers/settings/system.proto
new file mode 100644
index 0000000..6b6edd2
--- /dev/null
+++ b/core/proto/android/providers/settings/system.proto
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.providers.settings;
+
+option java_multiple_files = true;
+
+import "frameworks/base/core/proto/android/providers/settings/common.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
+// Note: it's a conscious decision to add each setting as a separate field. This
+// allows annotating each setting with its own privacy tag.
+message SystemSettingsProto {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ repeated SettingsOperationProto historical_operations = 1;
+
+ optional SettingProto advanced_settings = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Alarm {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // "alarm_alert" in code.
+ optional SettingProto default_uri = 1;
+ optional SettingProto alert_cache = 2;
+ }
+ optional Alarm alarm = 3;
+
+ message Bluetooth {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // Whether remote devices may discover and/or connect to this device:
+ // 2 -- discoverable and connectable
+ // 1 -- connectable but not discoverable
+ // 0 -- neither connectable nor discoverable
+ optional SettingProto discoverability = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto discoverability_timeout_secs = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Bluetooth bluetooth = 4;
+
+ optional SettingProto date_format = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto display_color_mode = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message DevOptions {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // Show pointer location on screen? 0 = no, 1 = yes. "pointer_location
+ // in code.
+ optional SettingProto pointer_location = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_touches = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Log raw orientation data from {@link
+ // com.android.server.policy.WindowOrientationListener} for use with the
+ // orientationplot.py tool.
+ // 0 = no, 1 = yes
+ optional SettingProto window_orientation_listener_log = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional DevOptions developer_options = 7;
+
+ message DtmfTone {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // "dtmf_tone_when_dialing" in code.
+ optional SettingProto play_when_dialing = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // "dtmf_tone_type_when_dialing" in code.
+ optional SettingProto type_played_when_dialing = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional DtmfTone dtmf_tone = 8;
+
+ optional SettingProto egg_mode = 9 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto end_button_behavior = 10 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto font_scale = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message HapticFeedback {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto intensity = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional HapticFeedback haptic_feedback = 12;
+
+ // Whether the hearing aid is enabled. The value is boolean (1 or 0).
+ optional SettingProto hearing_aid = 13 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto lock_to_app_enabled = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Lockscreen {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto sounds_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto disabled = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Lockscreen lockscreen = 15;
+
+ // The system default media button event receiver.
+ optional SettingProto media_button_receiver = 16;
+
+ message Notification {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto sound = 1;
+ optional SettingProto sound_cache = 2;
+ optional SettingProto light_pulse = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto vibration_intensity = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Notification notification = 17;
+
+ optional SettingProto pointer_speed = 18 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Ringtone {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // "ringtone" in code. The system-wide default ringtone URI.
+ optional SettingProto default_uri = 1;
+ optional SettingProto cache = 2;
+ }
+ optional Ringtone ringtone = 19;
+
+ message Rotation {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // Control whether the accelerometer will be used to change screen
+ // orientation. If 0, it will not be used unless explicitly requested
+ // by the application; if 1, it will be used by default unless
+ // explicitly disabled by the application.
+ optional SettingProto accelerometer_rotation = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Default screen rotation when no other policy applies.
+ // When accelerometer_rotation is zero and no on-screen Activity expresses a
+ // preference, this rotation value will be used. Must be one of the
+ // {@link android.view.Surface#ROTATION_0 Surface rotation constants}.
+ optional SettingProto user_rotation = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Control whether the rotation lock toggle in the System UI should be hidden.
+ // Typically this is done for accessibility purposes to make it harder for
+ // the user to accidentally toggle the rotation lock while the display rotation
+ // has been locked for accessibility.
+ // If 0, then rotation lock toggle is not hidden for accessibility (although it may be
+ // unavailable for other reasons). If 1, then the rotation lock toggle is hidden.
+ optional SettingProto hide_rotation_lock_toggle_for_accessibility = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Rotation rotation = 20;
+
+ // User-selected RTT mode. When on, outgoing and incoming calls will be
+ // answered as RTT calls when supported by the device and carrier. Boolean
+ // value.
+ optional SettingProto rtt_calling_mode = 21 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Screen {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto off_timeout = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto brightness = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto brightness_for_vr = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto brightness_mode = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto auto_brightness_adj = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Screen screen = 22;
+
+ optional SettingProto setup_wizard_has_run = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_battery_percent = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_gtalk_service_status = 25 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Sip {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto receive_calls = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto call_options = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto always = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto address_only = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Sip sip = 26;
+
+ optional SettingProto sound_effects_enabled = 27 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto system_locales = 28 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Text {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto auto_replace = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto auto_caps = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto auto_punctuate = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_password = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Text text = 29;
+
+ optional SettingProto time_12_24 = 30 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto tty_mode = 31 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Vibrate {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto on = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto input_devices = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Whether silent mode should allow vibration feedback. This is used
+ // internally in AudioService and the Sound settings activity to coordinate
+ // decoupling of vibrate and silent modes. This setting will likely be
+ // removed in a future release with support for audio/vibe feedback
+ // profiles.
+ // Not used anymore. On devices with vibrator, the user explicitly selects
+ // silent or vibrate mode. Kept for use by legacy database upgrade code in
+ // DatabaseHelper.
+ optional SettingProto in_silent = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto when_ringing = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Vibrate vibrate = 32;
+
+ message Volume {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto ring = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto system = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto voice = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto music = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto alarm = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto notification = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_sco = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto master = 9 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto master_mono = 10 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Determines which streams are affected by ringer mode changes. The stream
+ // type's bit will be set to 1 if it should be muted when going into an
+ // inaudible ringer mode.
+ optional SettingProto mode_ringer_streams_affected = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Which streams are affected by mute. The stream type's bit should be set
+ // to 1 if it should be muted when a mute request is received.
+ optional SettingProto mute_streams_affected = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Volume volume = 33;
+
+ optional SettingProto when_to_make_wifi_calls = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ // Please insert fields in alphabetical order and group them into messages
+ // if possible (to avoid reaching the method limit).
+ // Next tag = 35;
+}
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 8d4b56c..bb8ce81 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -578,6 +578,12 @@
optional .android.os.PersistableBundleProto extras = 14;
optional .android.os.BundleProto transient_extras = 15;
+ // ClipData of information that is returned to the application at
+ // execution time, but not persisted by the system. This is provided by
+ // the app and the main purpose of providing a ClipData is to allow
+ // granting of URI permissions for data associated with the clip. The
+ // exact kind of permission grant to perform is specified in the flags
+ // field.
optional .android.content.ClipDataProto clip_data = 16;
optional GrantedUriPermissionsDumpProto granted_uri_permissions = 17;
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 063135d..a8d0825 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -156,6 +156,8 @@
TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21;
TRANSIT_KEYGUARD_OCCLUDE = 22;
TRANSIT_KEYGUARD_UNOCCLUDE = 23;
+ TRANSIT_TRANSLUCENT_ACTIVITY_OPEN = 24;
+ TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE = 25;
}
optional TransitionType last_used_app_transition = 2;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c4d3667..4028ab5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -89,6 +89,8 @@
<protected-broadcast android:name="android.intent.action.OVERLAY_REMOVED" />
<protected-broadcast android:name="android.intent.action.OVERLAY_PRIORITY_CHANGED" />
<protected-broadcast android:name="android.intent.action.USER_ACTIVITY_NOTIFICATION" />
+ <protected-broadcast android:name="android.intent.action.MY_PACKAGE_SUSPENDED" />
+ <protected-broadcast android:name="android.intent.action.MY_PACKAGE_UNSUSPENDED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" />
@@ -1102,6 +1104,8 @@
<!-- Allows an app to use fingerprint hardware.
<p>Protection level: normal
+ @deprecated Applications should request {@link
+ android.Manifest.permission#USE_BIOMETRIC} instead
-->
<permission android:name="android.permission.USE_FINGERPRINT"
android:permissionGroup="android.permission-group.SENSORS"
@@ -1109,6 +1113,15 @@
android:description="@string/permdesc_useFingerprint"
android:protectionLevel="normal" />
+ <!-- Allows an app to use device supported biometric modalities.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.USE_BIOMETRIC"
+ android:permissionGroup="android.permission-group.SENSORS"
+ android:label="@string/permlab_useBiometric"
+ android:description="@string/permdesc_useBiometric"
+ android:protectionLevel="normal" />
+
<!-- ====================================================================== -->
<!-- REMOVED PERMISSIONS -->
<!-- ====================================================================== -->
@@ -4229,6 +4242,16 @@
android:exported="false">
</receiver>
+ <receiver android:name="com.android.server.am.BatteryStatsService$UsbConnectionReceiver"
+ android:exported="false">
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.hardware.usb.action.USB_STATE" />
+ </intent-filter>
+ </receiver>
+
<service android:name="android.hardware.location.GeofenceHardwareService"
android:permission="android.permission.LOCATION_HARDWARE"
android:exported="false" />
diff --git a/core/res/res/anim/activity_translucent_close_exit.xml b/core/res/res/anim/activity_translucent_close_exit.xml
new file mode 100644
index 0000000..04c5dea
--- /dev/null
+++ b/core/res/res/anim/activity_translucent_close_exit.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:zAdjustment="top">
+ <translate
+ android:fromYDelta="0%"
+ android:toYDelta="100%"
+ android:interpolator="@interpolator/fast_out_linear_in"
+ android:duration="300"/>
+</set>
diff --git a/core/res/res/anim/activity_translucent_open_enter.xml b/core/res/res/anim/activity_translucent_open_enter.xml
new file mode 100644
index 0000000..da3dded
--- /dev/null
+++ b/core/res/res/anim/activity_translucent_open_enter.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false">
+ <translate
+ android:fromYDelta="100%"
+ android:toYDelta="0"
+ android:interpolator="@interpolator/linear_out_slow_in"
+ android:duration="300"/>
+</set>
diff --git a/core/res/res/layout/autofill_dataset_picker_header_footer.xml b/core/res/res/layout/autofill_dataset_picker_header_footer.xml
new file mode 100644
index 0000000..048494a
--- /dev/null
+++ b/core/res/res/layout/autofill_dataset_picker_header_footer.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<view xmlns:android="http://schemas.android.com/apk/res/android"
+ class="com.android.server.autofill.ui.FillUi$AutofillFrameLayout"
+ android:id="@+id/autofill_dataset_picker"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ style="@style/AutofillDatasetPicker">
+
+ <LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/autofill_dataset_header"
+ android:visibility="gone"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"/>
+
+ <ListView
+ android:id="@+id/autofill_dataset_list"
+ android:layout_weight="1"
+ android:layout_width="fill_parent"
+ android:layout_height="0dp"
+ android:drawSelectorOnTop="true"
+ android:clickable="true"
+ android:divider="@null"
+ android:visibility="gone">
+ </ListView>
+
+ <LinearLayout
+ android:id="@+id/autofill_dataset_footer"
+ android:visibility="gone"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"/>
+
+ </LinearLayout>
+
+</view>
diff --git a/core/res/res/layout/autofill_dataset_picker_header_footer_fullscreen.xml b/core/res/res/layout/autofill_dataset_picker_header_footer_fullscreen.xml
new file mode 100644
index 0000000..24b14a0
--- /dev/null
+++ b/core/res/res/layout/autofill_dataset_picker_header_footer_fullscreen.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/autofill_dataset_picker"
+ style="@style/AutofillDatasetPicker"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autofill_window_title"
+ android:layout_above="@+id/autofill_dataset_container"
+ android:layout_alignStart="@+id/autofill_dataset_container"
+ android:textSize="16sp"/>
+
+ <!-- autofill_container is the common parent for inserting authentication item or
+ autofill_dataset_list-->
+ <FrameLayout
+ android:id="@+id/autofill_dataset_container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerInParent="true">
+
+ <LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/autofill_dataset_header"
+ android:visibility="gone"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"/>
+
+ <ListView
+ android:id="@+id/autofill_dataset_list"
+ android:layout_weight="1"
+ android:layout_width="fill_parent"
+ android:layout_height="0dp"
+ android:clickable="true"
+ android:divider="@null"
+ android:drawSelectorOnTop="true"
+ android:visibility="gone"/>
+
+ <LinearLayout
+ android:id="@+id/autofill_dataset_footer"
+ android:visibility="gone"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"/>
+
+ </LinearLayout>
+
+ </FrameLayout>
+
+</RelativeLayout>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index 265eaaf..351bd81 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -29,7 +29,10 @@
<!-- Height of the status bar -->
<dimen name="status_bar_height">@dimen/status_bar_height_landscape</dimen>
-
+ <!-- Height of area above QQS where battery/time go -->
+ <dimen name="quick_qs_offset_height">@dimen/status_bar_height_landscape</dimen>
+ <!-- Total height of QQS in landscape, this is effectively status_bar_height_landscape + 128 -->
+ <dimen name="quick_qs_total_height">152dp</dimen>
<!-- Default height of an action bar. -->
<dimen name="action_bar_default_height">40dip</dimen>
<!-- Vertical padding around action bar icons. -->
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 3135455..aceba08 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2123,44 +2123,48 @@
<!-- Controls how the window is laid out if there is a {@code DisplayCutout}.
<p>
Defaults to {@code default}.
-
- @see android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
- @see android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
- @see android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
- @see android.view.DisplayCutout
- @see android.R.attr#layoutInDisplayCutoutMode -->
+ <p>
+ See also
+ {@link android.view.WindowManager.LayoutParams#layoutInDisplayCutoutMode
+ WindowManager.LayoutParams.layoutInDisplayCutoutMode},
+ {@link android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT},
+ {@link android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES},
+ {@link android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER},
+ and {@link android.view.DisplayCutout DisplayCutout}
+ -->
<attr name="windowLayoutInDisplayCutoutMode">
- <!-- The window is allowed to extend into the {@code DisplayCutout} area, only if the
- {@code DisplayCutout} is fully contained within a system bar. Otherwise, the window is
- laid out such that it does not overlap with the {@code DisplayCutout} area.
-
- @see android.view.DisplayCutout
- @see android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
+ <!-- <p>
+ The window is allowed to extend into the <code>DisplayCutout</code> area, only if
+ the <code>DisplayCutout</code> is fully contained within a system bar. Otherwise, the
+ window is laid out such that it does not overlap with the <code>DisplayCutout</code>
+ area.
+ <p>
+ Corresponds to <code>LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT</code>.
-->
<enum name="default" value="0" />
- <!--
- The window is always allowed to extend into the {@code DisplayCutout} areas on the short
- edges of the screen even if fullscreen or in landscape.
- The window will never extend into a {@link DisplayCutout} area on the long edges of the
- screen.
+ <!-- <p>
+ The window is always allowed to extend into the <code>DisplayCutout</code> areas on the
+ short edges of the screen even if fullscreen or in landscape.
+ The window will never extend into a <code>DisplayCutout</code> area on the long edges of
+ the screen.
<p>
The window must make sure that no important content overlaps with the
- {@link DisplayCutout}.
-
- @see android.view.DisplayCutout
- @see android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
+ <code>DisplayCutout</code>.
+ <p>
+ Corresponds to <code>LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES</code>.
-->
<enum name="shortEdges" value="1" />
- <!-- Use {@code shortEdges} instead. This is temporarily here to unblock pushing the SDK
- until all usages have been migrated to {@code shortEdges} -->
+ <!-- Use <code>shortEdges</code> instead. This is temporarily here to unblock pushing
+ the SDK until all usages have been migrated to <code>shortEdges</code> -->
<enum name="always" value="1" />
- <!-- The window is never allowed to overlap with the DisplayCutout area.
+ <!-- <p>
+ The window is never allowed to overlap with the <code>DisplayCutout</code> area.
<p>
- This should be used with windows that transiently set {@code SYSTEM_UI_FLAG_FULLSCREEN}
- to avoid a relayout of the window when the flag is set or cleared.
-
- @see android.view.DisplayCutout
- @see android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
+ This should be used with windows that transiently set
+ <code>SYSTEM_UI_FLAG_FULLSCREEN</code> to avoid a relayout of the window when the
+ flag is set or cleared.
+ <p>
+ Corresponds to <code>LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER</code>.
-->
<enum name="never" value="2" />
</attr>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b5e223c..66d25df 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1095,6 +1095,9 @@
<!-- Display low battery warning when battery level dips to this value -->
<integer name="config_lowBatteryWarningLevel">15</integer>
+ <!-- The default suggested battery % at which we enable battery saver automatically. -->
+ <integer name="config_lowBatteryAutoTriggerDefaultLevel">15</integer>
+
<!-- Close low battery warning when battery level reaches the lowBatteryWarningLevel
plus this -->
<integer name="config_lowBatteryCloseWarningBump">5</integer>
@@ -1340,30 +1343,6 @@
<integer-array name="config_autoBrightnessKeyboardBacklightValues">
</integer-array>
- <!-- Array of light sensor lux values to define the minimum brightness curve, which guarantees
- that any curve that dips below it is rejected by the system.
- This prevents auto-brightness from setting the screen so dark as to prevent the user from
- disabling auto-brightness or reseting the brightness curve via ADB.
-
- The control points must be strictly increasing. Each control point corresponds to an entry
- in the minimum brightness nits array. -->
- <integer-array name="config_autoBrightnessMinimumBrightnessCurveLux">
- <item>2000</item>
- <item>4000</item>
- </integer-array>
-
- <!-- Array of desired screen brightness in nits corresponding to the lux values
- in the config_autoBrightnessMinimumBrightnessCurveLux array.
-
- This array should have size one greater than the size of the
- config_autoBrightnessMinimumBrightnessCurveLux array. The values must be non-negative and
- non-decreasing. -->
- <array name="config_autoBrightnessMinimumBrightnessCurveNits">
- <item>1.0</item>
- <item>50.0</item>
- <item>90.0</item>
- </array>
-
<!-- Array of hysteresis constraint values for brightening, represented as tenths of a
percent. The length of this array is assumed to be one greater than
config_dynamicHysteresisLuxLevels. The brightening threshold is calculated as
@@ -2389,19 +2368,6 @@
<item>com.android.inputmethod.latin</item>
</string-array>
- <!-- The list of carrier applications which should be disabled until used.
- This function suppresses update notifications for these pre-installed apps.
- In SubscriptionInfoUpdater, the listed applications are disabled until used when all of the
- following conditions are met.
- 1. Not currently carrier-privileged according to the inserted SIM
- 2. Pre-installed
- 3. In the default state (enabled but not explicitly)
- And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted
- that marks the app as carrier privileged. It also grants the app default permissions
- for Phone and Location. As such, apps MUST only ever be added to this list if they
- obtain user consent to access their location through other means. -->
- <string-array name="config_disabledUntilUsedPreinstalledCarrierApps" translatable="false" />
-
<!-- The list of classes that should be added to the notification ranking pipeline.
See {@link com.android.server.notification.NotificationSignalExtractor}
If you add a new extractor to this list make sure to update
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 2e8f663..49cd272 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1325,6 +1325,11 @@
disables the keylock when receiving an incoming phone call, then
re-enables the keylock when the call is finished.</string>
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=NONE] -->
+ <string name="permlab_useBiometric">use biometric hardware</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this.[CHAR_LIMIT=NONE] -->
+ <string name="permdesc_useBiometric">Allows the app to use biometric hardware for authentication</string>
+
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_manageFingerprint">manage fingerprint hardware</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -2752,30 +2757,57 @@
<!-- Label for item in the text selection menu to trigger an Email app [CHAR LIMIT=20] -->
<string name="email">Email</string>
+ <!-- Accessibility description for an item in the text selection menu to trigger an Email app [CHAR LIMIT=NONE] -->
+ <string name="email_desc">Email selected address</string>
+
<!-- Label for item in the text selection menu to trigger a Dialer app [CHAR LIMIT=20] -->
<string name="dial">Call</string>
+ <!-- Accessibility description for an item in the text selection menu to call a phone number [CHAR LIMIT=NONE] -->
+ <string name="dial_desc">Call selected phone number</string>
+
<!-- Label for item in the text selection menu to trigger a Map app [CHAR LIMIT=20] -->
<string name="map">Locate</string>
+ <!-- Accessibility description for an item in the text selection menu to open maps for an address [CHAR LIMIT=NONE] -->
+ <string name="map_desc">Locale selected address</string>
+
<!-- Label for item in the text selection menu to trigger a Browser app [CHAR LIMIT=20] -->
<string name="browse">Open</string>
+ <!-- Accessibility description for an item in the text selection menu to open a URL in a browser [CHAR LIMIT=NONE] -->
+ <string name="browse_desc">Open selected URL</string>
+
<!-- Label for item in the text selection menu to trigger an SMS app [CHAR LIMIT=20] -->
<string name="sms">Message</string>
+ <!-- Accessibility description for an item in the text selection menu to send an SMS to a phone number [CHAR LIMIT=NONE] -->
+ <string name="sms_desc">Message selected phone number</string>
+
<!-- Label for item in the text selection menu to trigger adding a contact [CHAR LIMIT=20] -->
<string name="add_contact">Add</string>
+ <!-- Accessibility description for an item in the text selection menu to add the selected detail to contacts [CHAR LIMIT=NONE] -->
+ <string name="add_contact_desc">Add to contacts</string>
+
<!-- Label for item in the text selection menu to view the calendar for the selected time/date [CHAR LIMIT=20] -->
<string name="view_calendar">View</string>
+ <!-- Accessibility description for an item in the text selection menu to view the calendar for a date [CHAR LIMIT=NONE]-->
+ <string name="view_calendar_desc">View selected time in calendar</string>
+
<!-- Label for item in the text selection menu to create a calendar event at the selected time/date [CHAR LIMIT=20] -->
<string name="add_calendar_event">Schedule</string>
+ <!-- Accessibility description for an item in the text selection menu to schedule an event for a date [CHAR LIMIT=NONE] -->
+ <string name="add_calendar_event_desc">Schedule event for selected time</string>
+
<!-- Label for item in the text selection menu to track a selected flight number [CHAR LIMIT=20] -->
<string name="view_flight">Track</string>
+ <!-- Accessibility description for an item in the text selection menu to track a flight [CHAR LIMIT=NONE] -->
+ <string name="view_flight_desc">Track selected flight</string>
+
<!-- If the device is getting low on internal storage, a notification is shown to the user. This is the title of that notification. -->
<string name="low_internal_storage_view_title">Storage space running out</string>
<!-- If the device is getting low on internal storage, a notification is shown to the user. This is the message of that notification. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5eeb418..c73a7cb 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -545,14 +545,23 @@
<java-symbol type="string" name="undo" />
<java-symbol type="string" name="redo" />
<java-symbol type="string" name="email" />
+ <java-symbol type="string" name="email_desc" />
<java-symbol type="string" name="dial" />
+ <java-symbol type="string" name="dial_desc" />
<java-symbol type="string" name="map" />
+ <java-symbol type="string" name="map_desc" />
<java-symbol type="string" name="browse" />
+ <java-symbol type="string" name="browse_desc" />
<java-symbol type="string" name="sms" />
+ <java-symbol type="string" name="sms_desc" />
<java-symbol type="string" name="add_contact" />
+ <java-symbol type="string" name="add_contact_desc" />
<java-symbol type="string" name="view_calendar" />
+ <java-symbol type="string" name="view_calendar_desc" />
<java-symbol type="string" name="add_calendar_event" />
+ <java-symbol type="string" name="add_calendar_event_desc" />
<java-symbol type="string" name="view_flight" />
+ <java-symbol type="string" name="view_flight_desc" />
<java-symbol type="string" name="textSelectionCABTitle" />
<java-symbol type="string" name="BaMmi" />
<java-symbol type="string" name="CLIRDefaultOffNextCallOff" />
@@ -1233,7 +1242,6 @@
<java-symbol type="array" name="supported_locales" />
<java-symbol type="array" name="config_cdma_dun_supported_types" />
<java-symbol type="array" name="config_disabledUntilUsedPreinstalledImes" />
- <java-symbol type="array" name="config_disabledUntilUsedPreinstalledCarrierApps" />
<java-symbol type="array" name="config_callBarringMMI" />
<java-symbol type="array" name="config_globalActionsList" />
<java-symbol type="array" name="config_telephonyEuiccDeviceCapabilities" />
@@ -1611,6 +1619,8 @@
<java-symbol type="anim" name="task_open_enter" />
<java-symbol type="anim" name="cross_profile_apps_thumbnail_enter" />
<java-symbol type="anim" name="task_open_enter_cross_profile_apps" />
+ <java-symbol type="anim" name="activity_translucent_open_enter" />
+ <java-symbol type="anim" name="activity_translucent_close_exit" />
<java-symbol type="array" name="config_autoRotationTiltTolerance" />
<java-symbol type="array" name="config_keyboardTapVibePattern" />
@@ -1660,6 +1670,7 @@
<java-symbol type="dimen" name="navigation_bar_height_landscape_car_mode" />
<java-symbol type="dimen" name="navigation_bar_width_car_mode" />
<java-symbol type="dimen" name="status_bar_height" />
+ <java-symbol type="dimen" name="quick_qs_offset_height" />
<java-symbol type="dimen" name="quick_qs_total_height" />
<java-symbol type="drawable" name="ic_jog_dial_sound_off" />
<java-symbol type="drawable" name="ic_jog_dial_sound_on" />
@@ -1794,8 +1805,6 @@
<java-symbol type="array" name="config_autoBrightnessKeyboardBacklightValues" />
<java-symbol type="array" name="config_autoBrightnessLcdBacklightValues" />
<java-symbol type="array" name="config_autoBrightnessLevels" />
- <java-symbol type="array" name="config_autoBrightnessMinimumBrightnessCurveLux" />
- <java-symbol type="array" name="config_autoBrightnessMinimumBrightnessCurveNits" />
<java-symbol type="array" name="config_dynamicHysteresisBrightLevels" />
<java-symbol type="array" name="config_dynamicHysteresisDarkLevels" />
<java-symbol type="array" name="config_dynamicHysteresisLuxLevels" />
@@ -3021,7 +3030,11 @@
<java-symbol type="layout" name="autofill_save"/>
<java-symbol type="layout" name="autofill_dataset_picker"/>
<java-symbol type="layout" name="autofill_dataset_picker_fullscreen"/>
+ <java-symbol type="layout" name="autofill_dataset_picker_header_footer"/>
+ <java-symbol type="layout" name="autofill_dataset_picker_header_footer_fullscreen"/>
<java-symbol type="id" name="autofill_dataset_container"/>
+ <java-symbol type="id" name="autofill_dataset_footer"/>
+ <java-symbol type="id" name="autofill_dataset_header"/>
<java-symbol type="id" name="autofill_dataset_list"/>
<java-symbol type="id" name="autofill_dataset_picker"/>
<java-symbol type="id" name="autofill" />
@@ -3314,4 +3327,6 @@
<java-symbol type="string" name="notification_app_name_system" />
<java-symbol type="string" name="notification_app_name_settings" />
+ <java-symbol type="integer" name="config_lowBatteryAutoTriggerDefaultLevel" />
+
</resources>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 6ef773a..2a3fcad 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -586,7 +586,8 @@
Settings.Secure.PARENTAL_CONTROL_REDIRECT_URL,
Settings.Secure.BLUETOOTH_ON_WHILE_DRIVING,
Settings.Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT,
- Settings.Secure.LOW_POWER_WARNING_ACKNOWLEDGED);
+ Settings.Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
+ Settings.Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION);
@Test
public void systemSettingsBackedUpOrBlacklisted() {
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
index 57db153..f96027d 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
@@ -126,11 +126,7 @@
TextClassification classification = mClassifier.classifyText(
text, startIndex, endIndex, mClassificationOptions);
- assertThat(classification,
- isTextClassification(
- classifiedText,
- TextClassifier.TYPE_EMAIL,
- "mailto:" + classifiedText));
+ assertThat(classification, isTextClassification(classifiedText, TextClassifier.TYPE_EMAIL));
}
@Test
@@ -144,11 +140,7 @@
TextClassification classification = mClassifier.classifyText(
text, startIndex, endIndex, mClassificationOptions);
- assertThat(classification,
- isTextClassification(
- classifiedText,
- TextClassifier.TYPE_URL,
- "http://" + classifiedText));
+ assertThat(classification, isTextClassification(classifiedText, TextClassifier.TYPE_URL));
}
@Test
@@ -158,11 +150,7 @@
String text = "Brandschenkestrasse 110, Zürich, Switzerland";
TextClassification classification = mClassifier.classifyText(
text, 0, text.length(), mClassificationOptions);
- assertThat(classification,
- isTextClassification(
- text,
- TextClassifier.TYPE_ADDRESS,
- "geo:0,0?q=Brandschenkestrasse+110%2C+Z%C3%BCrich%2C+Switzerland"));
+ assertThat(classification, isTextClassification(text, TextClassifier.TYPE_ADDRESS));
}
@Test
@@ -176,11 +164,7 @@
TextClassification classification = mClassifier.classifyText(
text, startIndex, endIndex, mClassificationOptions);
- assertThat(classification,
- isTextClassification(
- classifiedText,
- TextClassifier.TYPE_URL,
- "http://ANDROID.COM"));
+ assertThat(classification, isTextClassification(classifiedText, TextClassifier.TYPE_URL));
}
@Test
@@ -194,11 +178,7 @@
TextClassification classification = mClassifier.classifyText(
text, startIndex, endIndex, mClassificationOptions);
- assertThat(classification,
- isTextClassification(
- classifiedText,
- TextClassifier.TYPE_DATE,
- null));
+ assertThat(classification, isTextClassification(classifiedText, TextClassifier.TYPE_DATE));
}
@Test
@@ -213,10 +193,7 @@
TextClassification classification = mClassifier.classifyText(
text, startIndex, endIndex, mClassificationOptions);
assertThat(classification,
- isTextClassification(
- classifiedText,
- TextClassifier.TYPE_DATE_TIME,
- null));
+ isTextClassification(classifiedText, TextClassifier.TYPE_DATE_TIME));
}
@Test
@@ -355,39 +332,15 @@
}
private static Matcher<TextClassification> isTextClassification(
- final String text, final String type, final String intentUri) {
+ final String text, final String type) {
return new BaseMatcher<TextClassification>() {
@Override
public boolean matches(Object o) {
if (o instanceof TextClassification) {
TextClassification result = (TextClassification) o;
- final boolean typeRequirementSatisfied;
- String scheme;
- switch (type) {
- case TextClassifier.TYPE_EMAIL:
- scheme = result.getIntent().getData().getScheme();
- typeRequirementSatisfied = "mailto".equals(scheme);
- break;
- case TextClassifier.TYPE_URL:
- scheme = result.getIntent().getData().getScheme();
- typeRequirementSatisfied = "http".equals(scheme)
- || "https".equals(scheme);
- break;
- case TextClassifier.TYPE_ADDRESS:
- scheme = result.getIntent().getData().getScheme();
- typeRequirementSatisfied = "geo".equals(scheme);
- break;
- default:
- typeRequirementSatisfied = true;
- }
-
- return typeRequirementSatisfied
- && text.equals(result.getText())
+ return text.equals(result.getText())
&& result.getEntityCount() > 0
- && type.equals(result.getEntity(0))
- && (intentUri == null
- || intentUri.equals(result.getIntent().getDataString()));
- // TODO: Include other properties.
+ && type.equals(result.getEntity(0));
}
return false;
}
@@ -395,8 +348,7 @@
@Override
public void describeTo(Description description) {
description.appendText("text=").appendValue(text)
- .appendText(", type=").appendValue(type)
- .appendText(", intent.data=").appendValue(intentUri);
+ .appendText(", type=").appendValue(type);
}
};
}
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
index ada19fc..afc4bd5 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
@@ -17,15 +17,19 @@
package android.view.textclassifier;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import android.app.PendingIntent;
+import android.app.RemoteAction;
+import android.content.Context;
import android.content.Intent;
-import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Icon;
import android.os.LocaleList;
import android.os.Parcel;
+import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
@@ -41,47 +45,44 @@
@RunWith(AndroidJUnit4.class)
public class TextClassificationTest {
- public BitmapDrawable generateTestDrawable(int width, int height, int colorValue) {
+ public Icon generateTestIcon(int width, int height, int colorValue) {
final int numPixels = width * height;
final int[] colors = new int[numPixels];
for (int i = 0; i < numPixels; ++i) {
colors[i] = colorValue;
}
final Bitmap bitmap = Bitmap.createBitmap(colors, width, height, Bitmap.Config.ARGB_8888);
- final BitmapDrawable drawable = new BitmapDrawable(Resources.getSystem(), bitmap);
- drawable.setTargetDensity(bitmap.getDensity());
- return drawable;
+ return Icon.createWithBitmap(bitmap);
}
@Test
public void testParcel() {
+ final Context context = InstrumentationRegistry.getTargetContext();
final String text = "text";
- final BitmapDrawable primaryIcon = generateTestDrawable(16, 16, Color.RED);
- final String primaryLabel = "primarylabel";
- final Intent primaryIntent = new Intent("primaryintentaction");
- final View.OnClickListener primaryOnClick = v -> { };
- final BitmapDrawable secondaryIcon0 = generateTestDrawable(32, 288, Color.GREEN);
- final String secondaryLabel0 = "secondarylabel0";
- final Intent secondaryIntent0 = new Intent("secondaryintentaction0");
- final BitmapDrawable secondaryIcon1 = generateTestDrawable(576, 288, Color.BLUE);
- final String secondaryLabel1 = "secondaryLabel1";
- final Intent secondaryIntent1 = null;
- final BitmapDrawable secondaryIcon2 = null;
- final String secondaryLabel2 = null;
- final Intent secondaryIntent2 = new Intent("secondaryintentaction2");
- final ColorDrawable secondaryIcon3 = new ColorDrawable(Color.CYAN);
- final String secondaryLabel3 = null;
- final Intent secondaryIntent3 = null;
+
+ final Icon primaryIcon = generateTestIcon(576, 288, Color.BLUE);
+ final String primaryLabel = "primaryLabel";
+ final String primaryDescription = "primaryDescription";
+ final Intent primaryIntent = new Intent("primaryIntentAction");
+ final PendingIntent primaryPendingIntent = PendingIntent.getActivity(context, 0,
+ primaryIntent, 0);
+ final RemoteAction remoteAction0 = new RemoteAction(primaryIcon, primaryLabel,
+ primaryDescription, primaryPendingIntent);
+
+ final Icon secondaryIcon = generateTestIcon(32, 288, Color.GREEN);
+ final String secondaryLabel = "secondaryLabel";
+ final String secondaryDescription = "secondaryDescription";
+ final Intent secondaryIntent = new Intent("secondaryIntentAction");
+ final PendingIntent secondaryPendingIntent = PendingIntent.getActivity(context, 0,
+ secondaryIntent, 0);
+ final RemoteAction remoteAction1 = new RemoteAction(secondaryIcon, secondaryLabel,
+ secondaryDescription, secondaryPendingIntent);
+
final String signature = "signature";
final TextClassification reference = new TextClassification.Builder()
.setText(text)
- .setPrimaryAction(primaryIntent, primaryLabel, primaryIcon)
- .setOnClickListener(primaryOnClick)
- .addSecondaryAction(null, null, null) // ignored
- .addSecondaryAction(secondaryIntent0, secondaryLabel0, secondaryIcon0)
- .addSecondaryAction(secondaryIntent1, secondaryLabel1, secondaryIcon1)
- .addSecondaryAction(secondaryIntent2, secondaryLabel2, secondaryIcon2)
- .addSecondaryAction(secondaryIntent3, secondaryLabel3, secondaryIcon3)
+ .addAction(remoteAction0)
+ .addAction(remoteAction1)
.setEntityType(TextClassifier.TYPE_ADDRESS, 0.3f)
.setEntityType(TextClassifier.TYPE_PHONE, 0.7f)
.setSignature(signature)
@@ -95,45 +96,25 @@
assertEquals(text, result.getText());
assertEquals(signature, result.getSignature());
- assertEquals(4, result.getSecondaryActionsCount());
+ assertEquals(2, result.getActions().size());
- // Primary action (re-use existing icon).
- final Bitmap resPrimaryIcon = ((BitmapDrawable) result.getIcon()).getBitmap();
- assertEquals(primaryIcon.getBitmap().getPixel(0, 0), resPrimaryIcon.getPixel(0, 0));
- assertEquals(16, resPrimaryIcon.getWidth());
- assertEquals(16, resPrimaryIcon.getHeight());
- assertEquals(primaryLabel, result.getLabel());
- assertEquals(primaryIntent.getAction(), result.getIntent().getAction());
- assertEquals(null, result.getOnClickListener()); // Non-parcelable.
+ // Legacy API.
+ assertNull(result.getIcon());
+ assertNull(result.getLabel());
+ assertNull(result.getIntent());
+ assertNull(result.getOnClickListener());
- // Secondary action 0 (scale with height limit).
- final Bitmap resSecondaryIcon0 = ((BitmapDrawable) result.getSecondaryIcon(0)).getBitmap();
- assertEquals(secondaryIcon0.getBitmap().getPixel(0, 0), resSecondaryIcon0.getPixel(0, 0));
- assertEquals(16, resSecondaryIcon0.getWidth());
- assertEquals(144, resSecondaryIcon0.getHeight());
- assertEquals(secondaryLabel0, result.getSecondaryLabel(0));
- assertEquals(secondaryIntent0.getAction(), result.getSecondaryIntent(0).getAction());
+ // Primary action.
+ final RemoteAction primaryAction = result.getActions().get(0);
+ assertEquals(primaryLabel, primaryAction.getTitle());
+ assertEquals(primaryDescription, primaryAction.getContentDescription());
+ assertEquals(primaryPendingIntent, primaryAction.getActionIntent());
- // Secondary action 1 (scale with width limit).
- final Bitmap resSecondaryIcon1 = ((BitmapDrawable) result.getSecondaryIcon(1)).getBitmap();
- assertEquals(secondaryIcon1.getBitmap().getPixel(0, 0), resSecondaryIcon1.getPixel(0, 0));
- assertEquals(144, resSecondaryIcon1.getWidth());
- assertEquals(72, resSecondaryIcon1.getHeight());
- assertEquals(secondaryLabel1, result.getSecondaryLabel(1));
- assertEquals(null, result.getSecondaryIntent(1));
-
- // Secondary action 2 (no icon).
- assertEquals(null, result.getSecondaryIcon(2));
- assertEquals(null, result.getSecondaryLabel(2));
- assertEquals(secondaryIntent2.getAction(), result.getSecondaryIntent(2).getAction());
-
- // Secondary action 3 (convert non-bitmap drawable with negative size).
- final Bitmap resSecondaryIcon3 = ((BitmapDrawable) result.getSecondaryIcon(3)).getBitmap();
- assertEquals(secondaryIcon3.getColor(), resSecondaryIcon3.getPixel(0, 0));
- assertEquals(1, resSecondaryIcon3.getWidth());
- assertEquals(1, resSecondaryIcon3.getHeight());
- assertEquals(null, result.getSecondaryLabel(3));
- assertEquals(null, result.getSecondaryIntent(3));
+ // Secondary action.
+ final RemoteAction secondaryAction = result.getActions().get(1);
+ assertEquals(secondaryLabel, secondaryAction.getTitle());
+ assertEquals(secondaryDescription, secondaryAction.getContentDescription());
+ assertEquals(secondaryPendingIntent, secondaryAction.getActionIntent());
// Entities.
assertEquals(2, result.getEntityCount());
@@ -144,6 +125,43 @@
}
@Test
+ public void testParcelLegacy() {
+ final Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ final String text = "text";
+
+ final Icon icon = generateTestIcon(384, 192, Color.BLUE);
+ final String label = "label";
+ final Intent intent = new Intent("intent");
+ final View.OnClickListener onClickListener = v -> { };
+
+ final String signature = "signature";
+ final TextClassification reference = new TextClassification.Builder()
+ .setText(text)
+ .setIcon(icon.loadDrawable(context))
+ .setLabel(label)
+ .setIntent(intent)
+ .setOnClickListener(onClickListener)
+ .setEntityType(TextClassifier.TYPE_ADDRESS, 0.3f)
+ .setEntityType(TextClassifier.TYPE_PHONE, 0.7f)
+ .setSignature(signature)
+ .build();
+
+ // Parcel and unparcel
+ final Parcel parcel = Parcel.obtain();
+ reference.writeToParcel(parcel, reference.describeContents());
+ parcel.setDataPosition(0);
+ final TextClassification result = TextClassification.CREATOR.createFromParcel(parcel);
+
+ final Bitmap resultIcon = ((BitmapDrawable) result.getIcon()).getBitmap();
+ assertEquals(icon.getBitmap().getPixel(0, 0), resultIcon.getPixel(0, 0));
+ assertEquals(192, resultIcon.getWidth());
+ assertEquals(96, resultIcon.getHeight());
+ assertEquals(label, result.getLabel());
+ assertEquals(intent.getAction(), result.getIntent().getAction());
+ assertNull(result.getOnClickListener());
+ }
+
+ @Test
public void testParcelOptions() {
Calendar referenceTime = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.US);
referenceTime.setTimeInMillis(946771200000L); // 2000-01-02
diff --git a/docs/html/reference/images/display_cutout/default_mode/fullscreen_letterbox.png b/docs/html/reference/images/display_cutout/default_mode/fullscreen_letterbox.png
new file mode 100644
index 0000000..8602290
--- /dev/null
+++ b/docs/html/reference/images/display_cutout/default_mode/fullscreen_letterbox.png
Binary files differ
diff --git a/docs/html/reference/images/display_cutout/default_mode/landscape.png b/docs/html/reference/images/display_cutout/default_mode/landscape.png
new file mode 100644
index 0000000..be112f4
--- /dev/null
+++ b/docs/html/reference/images/display_cutout/default_mode/landscape.png
Binary files differ
diff --git a/docs/html/reference/images/display_cutout/default_mode/landscape_corner.png b/docs/html/reference/images/display_cutout/default_mode/landscape_corner.png
new file mode 100644
index 0000000..7aa92b4
--- /dev/null
+++ b/docs/html/reference/images/display_cutout/default_mode/landscape_corner.png
Binary files differ
diff --git a/docs/html/reference/images/display_cutout/default_mode/portrait.png b/docs/html/reference/images/display_cutout/default_mode/portrait.png
new file mode 100644
index 0000000..6392ad5
--- /dev/null
+++ b/docs/html/reference/images/display_cutout/default_mode/portrait.png
Binary files differ
diff --git a/docs/html/reference/images/display_cutout/default_mode/portrait_corner.png b/docs/html/reference/images/display_cutout/default_mode/portrait_corner.png
new file mode 100644
index 0000000..dc8e6d0
--- /dev/null
+++ b/docs/html/reference/images/display_cutout/default_mode/portrait_corner.png
Binary files differ
diff --git a/docs/html/reference/images/display_cutout/never_mode/landscape.png b/docs/html/reference/images/display_cutout/never_mode/landscape.png
new file mode 100644
index 0000000..be112f4
--- /dev/null
+++ b/docs/html/reference/images/display_cutout/never_mode/landscape.png
Binary files differ
diff --git a/docs/html/reference/images/display_cutout/never_mode/portrait_top_letterbox.png b/docs/html/reference/images/display_cutout/never_mode/portrait_top_letterbox.png
new file mode 100644
index 0000000..fc7dfcf
--- /dev/null
+++ b/docs/html/reference/images/display_cutout/never_mode/portrait_top_letterbox.png
Binary files differ
diff --git a/docs/html/reference/images/display_cutout/short_edge/fullscreen_corner_no_letterbox.png b/docs/html/reference/images/display_cutout/short_edge/fullscreen_corner_no_letterbox.png
new file mode 100644
index 0000000..09f942d
--- /dev/null
+++ b/docs/html/reference/images/display_cutout/short_edge/fullscreen_corner_no_letterbox.png
Binary files differ
diff --git a/docs/html/reference/images/display_cutout/short_edge/fullscreen_side_letterbox.png b/docs/html/reference/images/display_cutout/short_edge/fullscreen_side_letterbox.png
new file mode 100644
index 0000000..9aafc58
--- /dev/null
+++ b/docs/html/reference/images/display_cutout/short_edge/fullscreen_side_letterbox.png
Binary files differ
diff --git a/docs/html/reference/images/display_cutout/short_edge/fullscreen_top_no_letterbox.png b/docs/html/reference/images/display_cutout/short_edge/fullscreen_top_no_letterbox.png
new file mode 100644
index 0000000..75e913b
--- /dev/null
+++ b/docs/html/reference/images/display_cutout/short_edge/fullscreen_top_no_letterbox.png
Binary files differ
diff --git a/docs/html/reference/images/display_cutout/short_edge/landscape_corner.png b/docs/html/reference/images/display_cutout/short_edge/landscape_corner.png
new file mode 100644
index 0000000..d9e0f99
--- /dev/null
+++ b/docs/html/reference/images/display_cutout/short_edge/landscape_corner.png
Binary files differ
diff --git a/docs/html/reference/images/display_cutout/short_edge/landscape_sideboxed.png b/docs/html/reference/images/display_cutout/short_edge/landscape_sideboxed.png
new file mode 100644
index 0000000..9d44493
--- /dev/null
+++ b/docs/html/reference/images/display_cutout/short_edge/landscape_sideboxed.png
Binary files differ
diff --git a/docs/html/reference/images/display_cutout/short_edge/landscape_top_no_letterbox.png b/docs/html/reference/images/display_cutout/short_edge/landscape_top_no_letterbox.png
new file mode 100644
index 0000000..ac023c5
--- /dev/null
+++ b/docs/html/reference/images/display_cutout/short_edge/landscape_top_no_letterbox.png
Binary files differ
diff --git a/docs/html/reference/images/display_cutout/short_edge/portrait_side_letterbox.png b/docs/html/reference/images/display_cutout/short_edge/portrait_side_letterbox.png
new file mode 100644
index 0000000..50228db
--- /dev/null
+++ b/docs/html/reference/images/display_cutout/short_edge/portrait_side_letterbox.png
Binary files differ
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index 5dc4463..71ee6c2 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -41,13 +41,19 @@
/**
* Should only be assigned in constructors (or setBitmap if software canvas),
* freed by NativeAllocation.
+ * @hide
*/
protected long mNativeCanvasWrapper;
/**
* Used to determine when compatibility scaling is in effect.
+ * @hide
*/
protected int mScreenDensity = Bitmap.DENSITY_NONE;
+
+ /**
+ * @hide
+ */
protected int mDensity = Bitmap.DENSITY_NONE;
private boolean mAllowHwBitmapsInSwMode = false;
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index b0bc102..7080657 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -47,6 +47,7 @@
* Canvas and Drawables</a> developer guide.</p></div>
*/
public class Canvas extends BaseCanvas {
+ private static int sCompatiblityVersion = 0;
/** @hide */
public static boolean sCompatibilityRestore = false;
/** @hide */
@@ -306,7 +307,7 @@
/**
* Restore the current matrix when restore() is called.
- *
+ * @removed
* @deprecated Use the flagless version of {@link #save()}, {@link #saveLayer(RectF, Paint)} or
* {@link #saveLayerAlpha(RectF, int)}. For saveLayer() calls the matrix
* was always restored for {@link #isHardwareAccelerated() Hardware accelerated}
@@ -318,6 +319,7 @@
/**
* Restore the current clip when restore() is called.
*
+ * @removed
* @deprecated Use the flagless version of {@link #save()}, {@link #saveLayer(RectF, Paint)} or
* {@link #saveLayerAlpha(RectF, int)}. For saveLayer() calls the clip
* was always restored for {@link #isHardwareAccelerated() Hardware accelerated}
@@ -329,6 +331,7 @@
/**
* The layer requires a per-pixel alpha channel.
*
+ * @removed
* @deprecated This flag is ignored. Use the flagless version of {@link #saveLayer(RectF, Paint)}
* {@link #saveLayerAlpha(RectF, int)}.
*/
@@ -337,6 +340,7 @@
/**
* The layer requires full 8-bit precision for each color channel.
*
+ * @removed
* @deprecated This flag is ignored. Use the flagless version of {@link #saveLayer(RectF, Paint)}
* {@link #saveLayerAlpha(RectF, int)}.
*/
@@ -349,6 +353,7 @@
* <code>saveLayerAlpha()</code> variants. Not passing this flag generally
* triggers extremely poor performance with hardware accelerated rendering.
*
+ * @removed
* @deprecated This flag results in poor performance and the same effect can be achieved with
* a single layer or multiple draw commands with different clips.
*
@@ -362,6 +367,7 @@
* call to <code>saveLayer()</code> and <code>saveLayerAlpha()</code>
* variants.
*
+ * @removed There are no visible methods remaining that use this flag
* <p class="note"><strong>Note:</strong> all methods that accept this flag
* have flagless versions that are equivalent to passing this flag.
*/
@@ -393,6 +399,7 @@
* restore() is made, those calls will be forgotten, and the settings that
* existed before the save() will be reinstated.
*
+ * @removed
* @deprecated Use {@link #save()} instead.
* @param saveFlags flag bits that specify which parts of the Canvas state
* to save/restore
@@ -424,6 +431,7 @@
* {@link Paint#getColorFilter() ColorFilter} are applied when the
* offscreen bitmap is drawn back when restore() is called.
*
+ * @removed
* @deprecated Use {@link #saveLayer(RectF, Paint)} instead.
* @param bounds May be null. The maximum size the offscreen bitmap
* needs to be (in local coordinates)
@@ -473,8 +481,10 @@
/**
* Helper version of saveLayer() that takes 4 values rather than a RectF.
*
+ * @removed
* @deprecated Use {@link #saveLayer(float, float, float, float, Paint)} instead.
*/
+ @Deprecated
public int saveLayer(float left, float top, float right, float bottom, @Nullable Paint paint,
@Saveflags int saveFlags) {
return nSaveLayer(mNativeCanvasWrapper, left, top, right, bottom,
@@ -510,6 +520,7 @@
* The {@code alpha} parameter is applied when the offscreen bitmap is
* drawn back when restore() is called.
*
+ * @removed
* @deprecated Use {@link #saveLayerAlpha(RectF, int)} instead.
* @param bounds The maximum size the offscreen bitmap needs to be
* (in local coordinates)
@@ -542,8 +553,10 @@
/**
* Helper for saveLayerAlpha() that takes 4 values instead of a RectF.
*
+ * @removed
* @deprecated Use {@link #saveLayerAlpha(float, float, float, float, int)} instead.
*/
+ @Deprecated
public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
@Saveflags int saveFlags) {
alpha = Math.min(255, Math.max(0, alpha));
@@ -738,6 +751,14 @@
return m;
}
+ private static void checkValidClipOp(@NonNull Region.Op op) {
+ if (sCompatiblityVersion >= Build.VERSION_CODES.P
+ && op != Region.Op.INTERSECT && op != Region.Op.DIFFERENCE) {
+ throw new IllegalArgumentException(
+ "Invalid Region.Op - only INTERSECT and DIFFERENCE are allowed");
+ }
+ }
+
/**
* Modify the current clip with the specified rectangle.
*
@@ -750,9 +771,13 @@
* are intended to only expand the clip as a result of a restore operation. This enables a view
* parent to clip a canvas to clearly define the maximal drawing area of its children. The
* recommended alternative calls are {@link #clipRect(RectF)} and {@link #clipOutRect(RectF)};
+ *
+ * As of API Level API level {@value Build.VERSION_CODES#P} only {@link Region.Op#INTERSECT} and
+ * {@link Region.Op#DIFFERENCE} are valid Region.Op parameters.
*/
@Deprecated
public boolean clipRect(@NonNull RectF rect, @NonNull Region.Op op) {
+ checkValidClipOp(op);
return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
op.nativeInt);
}
@@ -770,9 +795,13 @@
* are intended to only expand the clip as a result of a restore operation. This enables a view
* parent to clip a canvas to clearly define the maximal drawing area of its children. The
* recommended alternative calls are {@link #clipRect(Rect)} and {@link #clipOutRect(Rect)};
+ *
+ * As of API Level API level {@value Build.VERSION_CODES#P} only {@link Region.Op#INTERSECT} and
+ * {@link Region.Op#DIFFERENCE} are valid Region.Op parameters.
*/
@Deprecated
public boolean clipRect(@NonNull Rect rect, @NonNull Region.Op op) {
+ checkValidClipOp(op);
return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
op.nativeInt);
}
@@ -846,10 +875,14 @@
* parent to clip a canvas to clearly define the maximal drawing area of its children. The
* recommended alternative calls are {@link #clipRect(float,float,float,float)} and
* {@link #clipOutRect(float,float,float,float)};
+ *
+ * As of API Level API level {@value Build.VERSION_CODES#P} only {@link Region.Op#INTERSECT} and
+ * {@link Region.Op#DIFFERENCE} are valid Region.Op parameters.
*/
@Deprecated
public boolean clipRect(float left, float top, float right, float bottom,
@NonNull Region.Op op) {
+ checkValidClipOp(op);
return nClipRect(mNativeCanvasWrapper, left, top, right, bottom, op.nativeInt);
}
@@ -932,9 +965,13 @@
* parent to clip a canvas to clearly define the maximal drawing area of its children. The
* recommended alternative calls are {@link #clipPath(Path)} and
* {@link #clipOutPath(Path)};
+ *
+ * As of API Level API level {@value Build.VERSION_CODES#P} only {@link Region.Op#INTERSECT} and
+ * {@link Region.Op#DIFFERENCE} are valid Region.Op parameters.
*/
@Deprecated
public boolean clipPath(@NonNull Path path, @NonNull Region.Op op) {
+ checkValidClipOp(op);
return nClipPath(mNativeCanvasWrapper, path.readOnlyNI(), op.nativeInt);
}
@@ -1220,7 +1257,10 @@
}
/** @hide */
- public static void setCompatibilityVersion(int apiLevel) { nSetCompatibilityVersion(apiLevel); }
+ public static void setCompatibilityVersion(int apiLevel) {
+ sCompatiblityVersion = apiLevel;
+ nSetCompatibilityVersion(apiLevel);
+ }
private static native void nFreeCaches();
private static native void nFreeTextLayoutCaches();
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 97edf22..1eebd26 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -318,13 +318,17 @@
* Retrieve the timestamp associated with the texture image set by the most recent call to
* updateTexImage.
*
- * This timestamp is in nanoseconds, and is normally monotonically increasing. The timestamp
- * should be unaffected by time-of-day adjustments, and for a camera should be strictly
- * monotonic but for a MediaPlayer may be reset when the position is set. The
- * specific meaning and zero point of the timestamp depends on the source providing images to
- * the SurfaceTexture. Unless otherwise specified by the image source, timestamps cannot
- * generally be compared across SurfaceTexture instances, or across multiple program
- * invocations. It is mostly useful for determining time offsets between subsequent frames.
+ * <p>This timestamp is in nanoseconds, and is normally monotonically increasing. The timestamp
+ * should be unaffected by time-of-day adjustments. The specific meaning and zero point of the
+ * timestamp depends on the source providing images to the SurfaceTexture. Unless otherwise
+ * specified by the image source, timestamps cannot generally be compared across SurfaceTexture
+ * instances, or across multiple program invocations. It is mostly useful for determining time
+ * offsets between subsequent frames.</p>
+ *
+ * <p>For camera sources, timestamps should be strictly monotonic. Timestamps from MediaPlayer
+ * sources may be reset when the playback position is set. For EGL and Vulkan producers, the
+ * timestamp is the desired present time set with the EGL_ANDROID_presentation_time or
+ * VK_GOOGLE_display_timing extensions.</p>
*/
public long getTimestamp() {
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index 09b3b9b..419eb24 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -243,13 +243,7 @@
// Check that user authentication related parameters are acceptable. This method
// will throw an IllegalStateException if there are issues (e.g., secure lock screen
// not set up).
- KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
- spec.isUserAuthenticationRequired(),
- spec.getUserAuthenticationValidityDurationSeconds(),
- spec.isUserAuthenticationValidWhileOnBody(),
- spec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
- spec.isUserConfirmationRequired());
+ KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), spec);
} catch (IllegalStateException | IllegalArgumentException e) {
throw new InvalidAlgorithmParameterException(e);
}
@@ -285,16 +279,7 @@
args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterPaddings);
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
- KeymasterUtils.addUserAuthArgs(args,
- spec.isUserAuthenticationRequired(),
- spec.getUserAuthenticationValidityDurationSeconds(),
- spec.isUserAuthenticationValidWhileOnBody(),
- spec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
- spec.isUserConfirmationRequired());
- if (spec.isTrustedUserPresenceRequired()) {
- args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED);
- }
+ KeymasterUtils.addUserAuthArgs(args, spec);
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
args,
mKeymasterAlgorithm,
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index e33e3cd..d68a33d 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -344,13 +344,7 @@
// Check that user authentication related parameters are acceptable. This method
// will throw an IllegalStateException if there are issues (e.g., secure lock screen
// not set up).
- KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
- mSpec.isUserAuthenticationRequired(),
- mSpec.getUserAuthenticationValidityDurationSeconds(),
- mSpec.isUserAuthenticationValidWhileOnBody(),
- mSpec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
- mSpec.isUserConfirmationRequired());
+ KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), mSpec);
} catch (IllegalArgumentException | IllegalStateException e) {
throw new InvalidAlgorithmParameterException(e);
}
@@ -541,13 +535,7 @@
args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterSignaturePaddings);
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
- KeymasterUtils.addUserAuthArgs(args,
- mSpec.isUserAuthenticationRequired(),
- mSpec.getUserAuthenticationValidityDurationSeconds(),
- mSpec.isUserAuthenticationValidWhileOnBody(),
- mSpec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
- mSpec.isUserConfirmationRequired());
+ KeymasterUtils.addUserAuthArgs(args, mSpec);
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
mSpec.getKeyValidityForOriginationEnd());
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 05cc74a..fc86ca0 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -497,13 +497,7 @@
importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterEncryptionPaddings);
importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING,
KeyProperties.SignaturePadding.allToKeymaster(spec.getSignaturePaddings()));
- KeymasterUtils.addUserAuthArgs(importArgs,
- spec.isUserAuthenticationRequired(),
- spec.getUserAuthenticationValidityDurationSeconds(),
- spec.isUserAuthenticationValidWhileOnBody(),
- spec.isInvalidatedByBiometricEnrollment(),
- spec.getBoundToSpecificSecureUserId(),
- spec.isUserConfirmationRequired());
+ KeymasterUtils.addUserAuthArgs(importArgs, spec);
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
spec.getKeyValidityStart());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
@@ -700,13 +694,7 @@
int[] keymasterPaddings = KeyProperties.EncryptionPadding.allToKeymaster(
params.getEncryptionPaddings());
args.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
- KeymasterUtils.addUserAuthArgs(args,
- params.isUserAuthenticationRequired(),
- params.getUserAuthenticationValidityDurationSeconds(),
- params.isUserAuthenticationValidWhileOnBody(),
- params.isInvalidatedByBiometricEnrollment(),
- params.getBoundToSpecificSecureUserId(),
- params.isUserConfirmationRequired());
+ KeymasterUtils.addUserAuthArgs(args, params);
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
args,
keymasterAlgorithm,
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index da23c70..4b9f3c80 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -21,6 +21,7 @@
import android.annotation.Nullable;
import android.app.KeyguardManager;
import android.hardware.fingerprint.FingerprintManager;
+import android.security.GateKeeper;
import android.security.KeyStore;
import android.text.TextUtils;
@@ -232,7 +233,7 @@
* key = (SecretKey) keyStore.getKey("key2", null);
* }</pre>
*/
-public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
+public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAuthArgs {
private static final X500Principal DEFAULT_CERT_SUBJECT = new X500Principal("CN=fake");
private static final BigInteger DEFAULT_CERT_SERIAL_NUMBER = new BigInteger("1");
@@ -669,6 +670,13 @@
}
/**
+ * @hide
+ */
+ public long getBoundToSpecificSecureUserId() {
+ return GateKeeper.INVALID_SECURE_USER_ID;
+ }
+
+ /**
* Builder of {@link KeyGenParameterSpec} instances.
*/
public final static class Builder {
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index b5b3281..95eeec7 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -212,7 +212,7 @@
* ...
* }</pre>
*/
-public final class KeyProtection implements ProtectionParameter {
+public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
private final Date mKeyValidityStart;
private final Date mKeyValidityForOriginationEnd;
private final Date mKeyValidityForConsumptionEnd;
@@ -224,6 +224,7 @@
private final boolean mRandomizedEncryptionRequired;
private final boolean mUserAuthenticationRequired;
private final int mUserAuthenticationValidityDurationSeconds;
+ private final boolean mTrustedUserPresenceRequred;
private final boolean mUserAuthenticationValidWhileOnBody;
private final boolean mInvalidatedByBiometricEnrollment;
private final long mBoundToSecureUserId;
@@ -242,6 +243,7 @@
boolean randomizedEncryptionRequired,
boolean userAuthenticationRequired,
int userAuthenticationValidityDurationSeconds,
+ boolean trustedUserPresenceRequred,
boolean userAuthenticationValidWhileOnBody,
boolean invalidatedByBiometricEnrollment,
long boundToSecureUserId,
@@ -260,6 +262,7 @@
mRandomizedEncryptionRequired = randomizedEncryptionRequired;
mUserAuthenticationRequired = userAuthenticationRequired;
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
+ mTrustedUserPresenceRequred = trustedUserPresenceRequred;
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
mBoundToSecureUserId = boundToSecureUserId;
@@ -437,6 +440,14 @@
}
/**
+ * Returns {@code true} if the key is authorized to be used only if a test of user presence has
+ * been performed between the {@code Signature.initSign()} and {@code Signature.sign()} calls.
+ */
+ public boolean isTrustedUserPresenceRequired() {
+ return mTrustedUserPresenceRequred;
+ }
+
+ /**
* Returns {@code true} if the key will be de-authorized when the device is removed from the
* user's body. This option has no effect on keys that don't have an authentication validity
* duration, and has no effect if the device lacks an on-body sensor.
@@ -509,6 +520,7 @@
private boolean mRandomizedEncryptionRequired = true;
private boolean mUserAuthenticationRequired;
private int mUserAuthenticationValidityDurationSeconds = -1;
+ private boolean mTrustedUserPresenceRequired = false;
private boolean mUserAuthenticationValidWhileOnBody;
private boolean mInvalidatedByBiometricEnrollment = true;
private boolean mUserConfirmationRequired;
@@ -811,6 +823,16 @@
}
/**
+ * Sets whether a test of user presence is required to be performed between the
+ * {@code Signature.initSign()} and {@code Signature.sign()} method calls.
+ */
+ @NonNull
+ public Builder setTrustedUserPresenceRequired(boolean required) {
+ mTrustedUserPresenceRequired = required;
+ return this;
+ }
+
+ /**
* Sets whether the key will remain authorized only until the device is removed from the
* user's body up to the limit of the authentication validity period (see
* {@link #setUserAuthenticationValidityDurationSeconds} and
@@ -910,6 +932,7 @@
mRandomizedEncryptionRequired,
mUserAuthenticationRequired,
mUserAuthenticationValidityDurationSeconds,
+ mTrustedUserPresenceRequired,
mUserAuthenticationValidWhileOnBody,
mInvalidatedByBiometricEnrollment,
mBoundToSecureUserId,
diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java
index 4e28601..0ef08f2 100644
--- a/keystore/java/android/security/keystore/KeymasterUtils.java
+++ b/keystore/java/android/security/keystore/KeymasterUtils.java
@@ -18,6 +18,7 @@
import android.util.Log;
import android.hardware.fingerprint.FingerprintManager;
+import android.os.UserHandle;
import android.security.GateKeeper;
import android.security.KeyStore;
import android.security.keymaster.KeymasterArguments;
@@ -101,22 +102,21 @@
* require user authentication.
*/
public static void addUserAuthArgs(KeymasterArguments args,
- boolean userAuthenticationRequired,
- int userAuthenticationValidityDurationSeconds,
- boolean userAuthenticationValidWhileOnBody,
- boolean invalidatedByBiometricEnrollment,
- long boundToSpecificSecureUserId,
- boolean userConfirmationRequired) {
- if (userConfirmationRequired) {
+ UserAuthArgs spec) {
+ if (spec.isUserConfirmationRequired()) {
args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED);
}
- if (!userAuthenticationRequired) {
+ if (spec.isTrustedUserPresenceRequired()) {
+ args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED);
+ }
+
+ if (!spec.isUserAuthenticationRequired()) {
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
return;
}
- if (userAuthenticationValidityDurationSeconds == -1) {
+ if (spec.getUserAuthenticationValidityDurationSeconds() == -1) {
// Every use of this key needs to be authorized by the user. This currently means
// fingerprint-only auth.
FingerprintManager fingerprintManager =
@@ -132,9 +132,9 @@
}
long sid;
- if (boundToSpecificSecureUserId != GateKeeper.INVALID_SECURE_USER_ID) {
- sid = boundToSpecificSecureUserId;
- } else if (invalidatedByBiometricEnrollment) {
+ if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) {
+ sid = spec.getBoundToSpecificSecureUserId();
+ } else if (spec.isInvalidatedByBiometricEnrollment()) {
// The fingerprint-only SID will change on fingerprint enrollment or removal of all,
// enrolled fingerprints, invalidating the key.
sid = fingerprintOnlySid;
@@ -147,14 +147,14 @@
args.addUnsignedLong(
KeymasterDefs.KM_TAG_USER_SECURE_ID, KeymasterArguments.toUint64(sid));
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT);
- if (userAuthenticationValidWhileOnBody) {
+ if (spec.isUserAuthenticationValidWhileOnBody()) {
throw new ProviderException("Key validity extension while device is on-body is not "
+ "supported for keys requiring fingerprint authentication");
}
} else {
long sid;
- if (boundToSpecificSecureUserId != GateKeeper.INVALID_SECURE_USER_ID) {
- sid = boundToSpecificSecureUserId;
+ if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) {
+ sid = spec.getBoundToSpecificSecureUserId();
} else {
// The key is authorized for use for the specified amount of time after the user has
// authenticated. Whatever unlocks the secure lock screen should authorize this key.
@@ -165,8 +165,8 @@
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE,
KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_FINGERPRINT);
args.addUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
- userAuthenticationValidityDurationSeconds);
- if (userAuthenticationValidWhileOnBody) {
+ spec.getUserAuthenticationValidityDurationSeconds());
+ if (spec.isUserAuthenticationValidWhileOnBody()) {
args.addBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY);
}
}
diff --git a/keystore/java/android/security/keystore/UserAuthArgs.java b/keystore/java/android/security/keystore/UserAuthArgs.java
new file mode 100644
index 0000000..1949592
--- /dev/null
+++ b/keystore/java/android/security/keystore/UserAuthArgs.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore;
+
+/**
+ * @hide
+ *
+ * This is an interface to encapsulate the user authentication arguments that
+ * are passed to KeymasterUtils.addUserAuthArgs. Classes that represent
+ * authorization characteristics for new or imported keys can implement this
+ * interface to be passed to that method.
+ */
+public interface UserAuthArgs {
+
+ boolean isUserAuthenticationRequired();
+ int getUserAuthenticationValidityDurationSeconds();
+ boolean isUserAuthenticationValidWhileOnBody();
+ boolean isInvalidatedByBiometricEnrollment();
+ boolean isUserConfirmationRequired();
+ long getBoundToSpecificSecureUserId();
+ boolean isTrustedUserPresenceRequired();
+
+}
diff --git a/libs/hwui/PathParser.cpp b/libs/hwui/PathParser.cpp
index a48fdfc..47fcca9 100644
--- a/libs/hwui/PathParser.cpp
+++ b/libs/hwui/PathParser.cpp
@@ -156,10 +156,63 @@
return;
}
-bool PathParser::isVerbValid(char verb) {
- verb = tolower(verb);
- return verb == 'a' || verb == 'c' || verb == 'h' || verb == 'l' || verb == 'm' || verb == 'q' ||
- verb == 's' || verb == 't' || verb == 'v' || verb == 'z';
+void PathParser::validateVerbAndPoints(char verb, size_t points, PathParser::ParseResult* result) {
+ size_t numberOfPointsExpected = -1;
+ switch (verb) {
+ case 'z':
+ case 'Z':
+ numberOfPointsExpected = 0;
+ break;
+ case 'm':
+ case 'l':
+ case 't':
+ case 'M':
+ case 'L':
+ case 'T':
+ numberOfPointsExpected = 2;
+ break;
+ case 'h':
+ case 'v':
+ case 'H':
+ case 'V':
+ numberOfPointsExpected = 1;
+ break;
+ case 'c':
+ case 'C':
+ numberOfPointsExpected = 6;
+ break;
+ case 's':
+ case 'q':
+ case 'S':
+ case 'Q':
+ numberOfPointsExpected = 4;
+ break;
+ case 'a':
+ case 'A':
+ numberOfPointsExpected = 7;
+ break;
+ default:
+ result->failureOccurred = true;
+ result->failureMessage += verb;
+ result->failureMessage += " is not a valid verb. ";
+ return;
+ }
+ if (numberOfPointsExpected == 0 && points == 0) {
+ return;
+ }
+ if (numberOfPointsExpected > 0 && points % numberOfPointsExpected == 0) {
+ return;
+ }
+
+ result->failureOccurred = true;
+ result->failureMessage += verb;
+ result->failureMessage += " needs to be followed by ";
+ if (numberOfPointsExpected > 0) {
+ result->failureMessage += "a multiple of ";
+ }
+ result->failureMessage += std::to_string(numberOfPointsExpected)
+ + " floats. However, " + std::to_string(points)
+ + " float(s) are found. ";
}
void PathParser::getPathDataFromAsciiString(PathData* data, ParseResult* result,
@@ -186,13 +239,11 @@
end = nextStart(pathStr, strLen, end);
std::vector<float> points;
getFloats(&points, result, pathStr, start, end);
- if (!isVerbValid(pathStr[start])) {
- result->failureOccurred = true;
- result->failureMessage = "Invalid pathData. Failure occurred at position " +
- std::to_string(start) + " of path: " + pathStr;
- }
- // If either verb or points is not valid, return immediately.
+ validateVerbAndPoints(pathStr[start], points.size(), result);
if (result->failureOccurred) {
+ // If either verb or points is not valid, return immediately.
+ result->failureMessage += "Failure occurred at position " +
+ std::to_string(start) + " of path: " + pathStr;
return;
}
data->verbs.push_back(pathStr[start]);
@@ -203,9 +254,10 @@
}
if ((end - start) == 1 && start < strLen) {
- if (!isVerbValid(pathStr[start])) {
- result->failureOccurred = true;
- result->failureMessage = "Invalid pathData. Failure occurred at position " +
+ validateVerbAndPoints(pathStr[start], 0, result);
+ if (result->failureOccurred) {
+ // If either verb or points is not valid, return immediately.
+ result->failureMessage += "Failure occurred at position " +
std::to_string(start) + " of path: " + pathStr;
return;
}
diff --git a/libs/hwui/PathParser.h b/libs/hwui/PathParser.h
index e4ec7be..474eb97 100644
--- a/libs/hwui/PathParser.h
+++ b/libs/hwui/PathParser.h
@@ -43,7 +43,7 @@
ANDROID_API static void getPathDataFromAsciiString(PathData* outData, ParseResult* result,
const char* pathStr, size_t strLength);
static void dump(const PathData& data);
- static bool isVerbValid(char verb);
+ static void validateVerbAndPoints(char verb, size_t points, ParseResult* result);
};
}; // namespace uirenderer
diff --git a/libs/hwui/tests/unit/VectorDrawableTests.cpp b/libs/hwui/tests/unit/VectorDrawableTests.cpp
index e7496f7..02f740c 100644
--- a/libs/hwui/tests/unit/VectorDrawableTests.cpp
+++ b/libs/hwui/tests/unit/VectorDrawableTests.cpp
@@ -242,7 +242,8 @@
{"\n \t z", true}, // Valid path data with leading spaces
{"1-2e34567", false}, // Not starting with a verb and ill-formatted float
{"f 4 5", false}, // Invalid verb
- {"\r ", false} // Empty string
+ {"\r ", false}, // Empty string
+ {"L1,0 L1,1 L0,1 z M1000", false} // Not enough floats following verb M.
};
static bool hasSameVerbs(const PathData& from, const PathData& to) {
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index 56edace..72d52d3 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -727,18 +727,7 @@
return false;
}
- if (format == ImageFormat.PRIVATE) {
- // Usage need to be either USAGE0_GPU_SAMPLED_IMAGE or USAGE0_VIDEO_ENCODE or combined.
- boolean isAllowed = (usage == HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
- isAllowed = isAllowed || (usage == HardwareBuffer.USAGE_VIDEO_ENCODE);
- isAllowed = isAllowed || (usage ==
- (HardwareBuffer.USAGE_VIDEO_ENCODE | HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE));
- return isAllowed;
- } else {
- // Usage need to make the buffer CPU readable for explicit format.
- return ((usage == HardwareBuffer.USAGE_CPU_READ_RARELY) ||
- (usage == HardwareBuffer.USAGE_CPU_READ_OFTEN));
- }
+ return true;
}
/**
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 1244d7f..7976f67 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -314,7 +314,9 @@
public void addStorage(StorageVolume storage) {
MtpStorage mtpStorage = mManager.addMtpStorage(storage);
mStorageMap.put(storage.getPath(), mtpStorage);
- mServer.addStorage(mtpStorage);
+ if (mServer != null) {
+ mServer.addStorage(mtpStorage);
+ }
}
public void removeStorage(StorageVolume storage) {
@@ -322,7 +324,9 @@
if (mtpStorage == null) {
return;
}
- mServer.removeStorage(mtpStorage);
+ if (mServer != null) {
+ mServer.removeStorage(mtpStorage);
+ }
mManager.removeMtpStorage(mtpStorage);
mStorageMap.remove(storage.getPath());
}
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 12d7440..4d8c96f 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "MtpDatabaseJNI"
#include "utils/Log.h"
+#include "utils/String8.h"
#include "android_media_Utils.h"
#include "mtp.h"
@@ -161,7 +162,7 @@
virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize);
virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle,
- MtpString& outFilePath,
+ MtpStringBuffer& outFilePath,
int64_t& outFileLength,
MtpObjectFormat& outFormat);
virtual MtpResponseCode beginDeleteObject(MtpObjectHandle handle);
@@ -287,7 +288,7 @@
jint* handles = env->GetIntArrayElements(array, 0);
jsize length = env->GetArrayLength(array);
for (int i = 0; i < length; i++)
- list->push(handles[i]);
+ list->push_back(handles[i]);
env->ReleaseIntArrayElements(array, handles, 0);
env->DeleteLocalRef(array);
@@ -316,7 +317,7 @@
jint* formats = env->GetIntArrayElements(array, 0);
jsize length = env->GetArrayLength(array);
for (int i = 0; i < length; i++)
- list->push(formats[i]);
+ list->push_back(formats[i]);
env->ReleaseIntArrayElements(array, formats, 0);
env->DeleteLocalRef(array);
@@ -334,7 +335,7 @@
jint* formats = env->GetIntArrayElements(array, 0);
jsize length = env->GetArrayLength(array);
for (int i = 0; i < length; i++)
- list->push(formats[i]);
+ list->push_back(formats[i]);
env->ReleaseIntArrayElements(array, formats, 0);
env->DeleteLocalRef(array);
@@ -352,7 +353,7 @@
jint* properties = env->GetIntArrayElements(array, 0);
jsize length = env->GetArrayLength(array);
for (int i = 0; i < length; i++)
- list->push(properties[i]);
+ list->push_back(properties[i]);
env->ReleaseIntArrayElements(array, properties, 0);
env->DeleteLocalRef(array);
@@ -370,7 +371,7 @@
jint* properties = env->GetIntArrayElements(array, 0);
jsize length = env->GetArrayLength(array);
for (int i = 0; i < length; i++)
- list->push(properties[i]);
+ list->push_back(properties[i]);
env->ReleaseIntArrayElements(array, properties, 0);
env->DeleteLocalRef(array);
@@ -826,7 +827,7 @@
MtpResponseCode MtpDatabase::getObjectInfo(MtpObjectHandle handle,
MtpObjectInfo& info) {
- MtpString path;
+ MtpStringBuffer path;
int64_t length;
MtpObjectFormat format;
@@ -861,8 +862,8 @@
info.mAssociationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
- MtpString temp(reinterpret_cast<char16_t*>(str));
- info.mName = strdup((const char *)temp);
+ MtpStringBuffer temp(str);
+ info.mName = strdup(temp);
env->ReleaseCharArrayElements(mStringBuffer, str, 0);
// read EXIF data for thumbnail information
@@ -901,9 +902,10 @@
case MTP_FORMAT_TIFF:
case MTP_FORMAT_TIFF_EP:
case MTP_FORMAT_DEFINED: {
- std::unique_ptr<FileStream> stream(new FileStream(path));
+ String8 temp(path);
+ std::unique_ptr<FileStream> stream(new FileStream(temp));
piex::PreviewImageData image_data;
- if (!GetExifFromRawImage(stream.get(), path, image_data)) {
+ if (!GetExifFromRawImage(stream.get(), temp, image_data)) {
// Couldn't parse EXIF data from a image file via piex.
break;
}
@@ -922,7 +924,7 @@
}
void* MtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
- MtpString path;
+ MtpStringBuffer path;
int64_t length;
MtpObjectFormat format;
void* result = NULL;
@@ -957,9 +959,10 @@
case MTP_FORMAT_TIFF:
case MTP_FORMAT_TIFF_EP:
case MTP_FORMAT_DEFINED: {
- std::unique_ptr<FileStream> stream(new FileStream(path));
+ String8 temp(path);
+ std::unique_ptr<FileStream> stream(new FileStream(temp));
piex::PreviewImageData image_data;
- if (!GetExifFromRawImage(stream.get(), path, image_data)) {
+ if (!GetExifFromRawImage(stream.get(), temp, image_data)) {
// Couldn't parse EXIF data from a image file via piex.
break;
}
@@ -992,7 +995,7 @@
}
MtpResponseCode MtpDatabase::getObjectFilePath(MtpObjectHandle handle,
- MtpString& outFilePath,
+ MtpStringBuffer& outFilePath,
int64_t& outFileLength,
MtpObjectFormat& outFormat) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
@@ -1004,8 +1007,7 @@
}
jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
- outFilePath.setTo(reinterpret_cast<char16_t*>(str),
- strlen16(reinterpret_cast<char16_t*>(str)));
+ outFilePath.set(str);
env->ReleaseCharArrayElements(mStringBuffer, str, 0);
jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
@@ -1146,7 +1148,7 @@
jint* handles = env->GetIntArrayElements(array, 0);
jsize length = env->GetArrayLength(array);
for (int i = 0; i < length; i++)
- list->push(handles[i]);
+ list->push_back(handles[i]);
env->ReleaseIntArrayElements(array, handles, 0);
env->DeleteLocalRef(array);
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index d42c39e..060eaf9 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -258,7 +258,7 @@
return NULL;
}
for (size_t i = 0; i < size; ++i) {
- elements[i] = deviceInfo->mOperations->itemAt(i);
+ elements[i] = static_cast<int>(deviceInfo->mOperations->at(i));
}
env->SetObjectField(info, field_deviceInfo_operationsSupported, operations.get());
}
@@ -274,7 +274,7 @@
return NULL;
}
for (size_t i = 0; i < size; ++i) {
- elements[i] = deviceInfo->mEvents->itemAt(i);
+ elements[i] = static_cast<int>(deviceInfo->mEvents->at(i));
}
env->SetObjectField(info, field_deviceInfo_eventsSupported, events.get());
}
@@ -296,7 +296,7 @@
int length = storageIDs->size();
jintArray array = env->NewIntArray(length);
// FIXME is this cast safe?
- env->SetIntArrayRegion(array, 0, length, (const jint *)storageIDs->array());
+ env->SetIntArrayRegion(array, 0, length, (const jint *)storageIDs->data());
delete storageIDs;
return array;
@@ -350,7 +350,7 @@
int length = handles->size();
jintArray array = env->NewIntArray(length);
// FIXME is this cast safe?
- env->SetIntArrayRegion(array, 0, length, (const jint *)handles->array());
+ env->SetIntArrayRegion(array, 0, length, (const jint *)handles->data());
delete handles;
return array;
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index 8730e06..c60590a 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -67,10 +67,10 @@
int controlFd = dup(jniGetFDFromFileDescriptor(env, jControlFd));
MtpServer* server = new MtpServer(getMtpDatabase(env, javaDatabase), controlFd,
usePtp,
- MtpString((deviceInfoManufacturerStr != NULL) ? deviceInfoManufacturerStr : ""),
- MtpString((deviceInfoModelStr != NULL) ? deviceInfoModelStr : ""),
- MtpString((deviceInfoDeviceVersionStr != NULL) ? deviceInfoDeviceVersionStr : ""),
- MtpString((deviceInfoSerialNumberStr != NULL) ? deviceInfoSerialNumberStr : ""));
+ (deviceInfoManufacturerStr != NULL) ? deviceInfoManufacturerStr : "",
+ (deviceInfoModelStr != NULL) ? deviceInfoModelStr : "",
+ (deviceInfoDeviceVersionStr != NULL) ? deviceInfoDeviceVersionStr : "",
+ (deviceInfoSerialNumberStr != NULL) ? deviceInfoSerialNumberStr : "");
if (deviceInfoManufacturerStr != NULL) {
env->ReleaseStringUTFChars(deviceInfoManufacturer, deviceInfoManufacturerStr);
}
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 7828c4c..dbdf5e16 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -35,6 +35,7 @@
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.widget.SwipeRefreshLayout;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.util.TypedValue;
@@ -531,7 +532,7 @@
private String getHeaderTitle() {
NetworkInfo info = mCm.getNetworkInfo(mNetwork);
- if (info == null) {
+ if (info == null || TextUtils.isEmpty(info.getExtraInfo())) {
return getString(R.string.action_bar_label);
}
NetworkCapabilities nc = mCm.getNetworkCapabilities(mNetwork);
diff --git a/packages/ExtServices/src/android/ext/services/notification/ChannelImpressions.java b/packages/ExtServices/src/android/ext/services/notification/ChannelImpressions.java
index 4ad4b24..de2659f 100644
--- a/packages/ExtServices/src/android/ext/services/notification/ChannelImpressions.java
+++ b/packages/ExtServices/src/android/ext/services/notification/ChannelImpressions.java
@@ -30,7 +30,7 @@
private static final String TAG = "ExtAssistant.CI";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- static final double DISMISS_TO_VIEW_RATIO_LIMIT = .8;
+ static final double DISMISS_TO_VIEW_RATIO_LIMIT = .4;
static final int STREAK_LIMIT = 2;
static final String ATT_DISMISSALS = "dismisses";
static final String ATT_VIEWS = "views";
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 584fc34..82bc6af8 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -500,10 +500,10 @@
<string name="keep_screen_on">Stay awake</string>
<!-- setting Checkbox summary whether to keep the screen on when plugged in -->
<string name="keep_screen_on_summary">Screen will never sleep while charging</string>
- <!-- Setting Checkbox title whether to enable bluetooth HCI snoop log -->
+ <!-- Setting Checkbox title whether to enable Bluetooth HCI snoop log -->
<string name="bt_hci_snoop_log">Enable Bluetooth HCI snoop log</string>
- <!-- setting Checkbox summary whether to capture all bluetooth HCI packets in a file -->
- <string name="bt_hci_snoop_log_summary">Capture all bluetooth HCI packets in a file</string>
+ <!-- setting Checkbox summary whether to capture all Bluetooth HCI packets in a file -->
+ <string name="bt_hci_snoop_log_summary">Capture all Bluetooth HCI packets in a file (Toggle Bluetooth after changing this setting)</string>
<!-- setting Checkbox title whether to enable OEM unlock [CHAR_LIMIT=35] -->
<string name="oem_unlock_enable">OEM unlocking</string>
<!-- setting Checkbox summary whether to enable OEM unlock [CHAR_LIMIT=50] -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
index 48b7c35..42b3156 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
@@ -16,20 +16,20 @@
package com.android.settingslib;
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
import android.content.Context;
import android.content.res.TypedArray;
import android.os.UserHandle;
+import android.support.v14.preference.SwitchPreference;
import android.support.v4.content.res.TypedArrayUtils;
import android.support.v7.preference.PreferenceManager;
import android.support.v7.preference.PreferenceViewHolder;
-import android.support.v14.preference.SwitchPreference;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.widget.TextView;
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
/**
* Version of SwitchPreference that can be disabled by a device admin
* using a user restriction.
@@ -37,7 +37,7 @@
public class RestrictedSwitchPreference extends SwitchPreference {
RestrictedPreferenceHelper mHelper;
boolean mUseAdditionalSummary = false;
- String mRestrictedSwitchSummary = null;
+ CharSequence mRestrictedSwitchSummary;
public RestrictedSwitchPreference(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
@@ -57,19 +57,15 @@
final TypedValue restrictedSwitchSummary = attributes.peekValue(
R.styleable.RestrictedSwitchPreference_restrictedSwitchSummary);
- CharSequence data = null;
if (restrictedSwitchSummary != null
&& restrictedSwitchSummary.type == TypedValue.TYPE_STRING) {
if (restrictedSwitchSummary.resourceId != 0) {
- data = context.getString(restrictedSwitchSummary.resourceId);
+ mRestrictedSwitchSummary =
+ context.getText(restrictedSwitchSummary.resourceId);
} else {
- data = restrictedSwitchSummary.string;
+ mRestrictedSwitchSummary = restrictedSwitchSummary.string;
}
}
- mRestrictedSwitchSummary = data == null ? null : data.toString();
- }
- if (mRestrictedSwitchSummary == null) {
- mRestrictedSwitchSummary = context.getString(R.string.disabled_by_admin);
}
if (mUseAdditionalSummary) {
setLayoutResource(R.layout.restricted_switch_preference);
@@ -94,6 +90,15 @@
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mHelper.onBindViewHolder(holder);
+
+ CharSequence switchSummary;
+ if (mRestrictedSwitchSummary == null) {
+ switchSummary = getContext().getText(isChecked()
+ ? R.string.enabled_by_admin : R.string.disabled_by_admin);
+ } else {
+ switchSummary = mRestrictedSwitchSummary;
+ }
+
final View restrictedIcon = holder.findViewById(R.id.restricted_icon);
final View switchWidget = holder.findViewById(android.R.id.switch_widget);
if (restrictedIcon != null) {
@@ -102,12 +107,13 @@
if (switchWidget != null) {
switchWidget.setVisibility(isDisabledByAdmin() ? View.GONE : View.VISIBLE);
}
+
if (mUseAdditionalSummary) {
final TextView additionalSummaryView = (TextView) holder.findViewById(
R.id.additional_summary);
if (additionalSummaryView != null) {
if (isDisabledByAdmin()) {
- additionalSummaryView.setText(mRestrictedSwitchSummary);
+ additionalSummaryView.setText(switchSummary);
additionalSummaryView.setVisibility(View.VISIBLE);
} else {
additionalSummaryView.setVisibility(View.GONE);
@@ -117,7 +123,7 @@
final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
if (summaryView != null) {
if (isDisabledByAdmin()) {
- summaryView.setText(mRestrictedSwitchSummary);
+ summaryView.setText(switchSummary);
summaryView.setVisibility(View.VISIBLE);
}
// No need to change the visibility to GONE in the else case here since Preference
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
index e2c7747..28833a3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
@@ -20,7 +20,9 @@
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
+import android.provider.Settings.Global;
import android.provider.Settings.Secure;
+import android.support.annotation.VisibleForTesting;
import android.util.Log;
/**
@@ -34,10 +36,27 @@
private static final boolean DEBUG = false;
- // Broadcast action for SystemUI to show the battery saver confirmation dialog.
+ private static final String SYSUI_PACKAGE = "com.android.systemui";
+
+ /** Broadcast action for SystemUI to show the battery saver confirmation dialog. */
public static final String ACTION_SHOW_START_SAVER_CONFIRMATION = "PNW.startSaverConfirmation";
/**
+ * Broadcast action for SystemUI to show the notification that suggests turning on
+ * automatic battery saver.
+ */
+ public static final String ACTION_SHOW_AUTO_SAVER_SUGGESTION
+ = "PNW.autoSaverSuggestion";
+
+ /**
+ * We show the auto battery saver suggestion notification when the user manually enables
+ * battery saver for the START_NTH time through the END_NTH time.
+ * (We won't show it for END_NTH + 1 time and after.)
+ */
+ private static final int AUTO_SAVER_SUGGESTION_START_NTH = 4;
+ private static final int AUTO_SAVER_SUGGESTION_END_NTH = 8;
+
+ /**
* Enable / disable battery saver by user request.
* - If it's the first time and needFirstTimeWarning, show the first time dialog.
* - If it's 4th time through 8th time, show the schedule suggestion notification.
@@ -62,11 +81,17 @@
if (context.getSystemService(PowerManager.class).setPowerSaveMode(enable)) {
if (enable) {
- Secure.putInt(cr, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT,
- Secure.getInt(cr, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, 0) + 1);
+ final int count =
+ Secure.getInt(cr, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, 0) + 1;
+ Secure.putInt(cr, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, count);
- // TODO If enabling, and the count is between 4 and 8 (inclusive), then
- // show the "battery saver schedule suggestion" notification.
+ if ((count >= AUTO_SAVER_SUGGESTION_START_NTH)
+ && (count <= AUTO_SAVER_SUGGESTION_END_NTH)
+ && Global.getInt(cr, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0) == 0
+ && Secure.getInt(cr,
+ Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION, 0) == 0) {
+ showAutoBatterySaverSuggestion(context);
+ }
}
return true;
@@ -79,13 +104,34 @@
Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 0) != 0) {
return false; // Already shown.
}
- final Intent i = new Intent(ACTION_SHOW_START_SAVER_CONFIRMATION);
- context.sendBroadcast(i);
-
+ context.sendBroadcast(getSystemUiBroadcast(ACTION_SHOW_START_SAVER_CONFIRMATION));
return true;
}
+ private static void showAutoBatterySaverSuggestion(Context context) {
+ context.sendBroadcast(getSystemUiBroadcast(ACTION_SHOW_AUTO_SAVER_SUGGESTION));
+ }
+
+ private static Intent getSystemUiBroadcast(String action) {
+ final Intent i = new Intent(action);
+ i.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ i.setPackage(SYSUI_PACKAGE);
+ return i;
+ }
+
private static void setBatterySaverConfirmationAcknowledged(Context context) {
Secure.putInt(context.getContentResolver(), Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1);
}
+
+ public static void suppressAutoBatterySaver(Context context) {
+ Secure.putInt(context.getContentResolver(),
+ Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION, 1);
+ }
+
+ public static void scheduleAutoBatterySaver(Context context, int level) {
+ if (Global.getInt(context.getContentResolver(), Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0)
+ == 0) {
+ Global.putInt(context.getContentResolver(), Global.LOW_POWER_MODE_TRIGGER_LEVEL, level);
+ }
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java
index 81a2d43..3e3c039 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java
@@ -41,10 +41,11 @@
public static final int SECONDS_PER_DAY = 24 * 60 * 60;
/**
- * Returns elapsed time for the given millis, in the following format:
- * 2d 5h 40m 29s
- * @param context the application context
- * @param millis the elapsed time in milli seconds
+ * Returns elapsed time for the given millis, in the following format:
+ * 2 days, 5 hr, 40 min, 29 sec
+ *
+ * @param context the application context
+ * @param millis the elapsed time in milli seconds
* @param withSeconds include seconds?
* @return the formatted elapsed time
*/
@@ -92,7 +93,7 @@
final Locale locale = context.getResources().getConfiguration().locale;
final MeasureFormat measureFormat = MeasureFormat.getInstance(
- locale, FormatWidth.NARROW);
+ locale, FormatWidth.SHORT);
sb.append(measureFormat.formatMeasures(measureArray));
if (measureArray.length == 1 && MeasureUnit.MINUTE.equals(measureArray[0].getUnit())) {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
index c11687b..05247ba 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
@@ -137,9 +137,9 @@
true /* basedOnUsage */);
// shortened string should not have percentage
- assertThat(info).isEqualTo("Less than 15m remaining");
+ assertThat(info).isEqualTo("Less than 15 min remaining");
// Add percentage to string when provided
- assertThat(info2).isEqualTo("Less than 15m remaining (10%)");
+ assertThat(info2).isEqualTo("Less than 15 min remaining (10%)");
}
@Test
@@ -154,9 +154,9 @@
false /* basedOnUsage */);
// We only add special mention for the long string
- assertThat(info).isEqualTo("About 1d 6h left based on your usage");
+ assertThat(info).isEqualTo("About 1 day, 6 hr left based on your usage");
// shortened string should not have extra text
- assertThat(info2).isEqualTo("About 1d 6h left (10%)");
+ assertThat(info2).isEqualTo("About 1 day, 6 hr left (10%)");
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
index 532c755..743951a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
@@ -43,7 +43,7 @@
@Test
public void testFormatElapsedTime_WithSeconds_ShowSeconds() {
final double testMillis = 5 * DateUtils.MINUTE_IN_MILLIS + 30 * DateUtils.SECOND_IN_MILLIS;
- final String expectedTime = "5m 30s";
+ final String expectedTime = "5 min, 30 sec";
assertThat(StringUtil.formatElapsedTime(mContext, testMillis, true).toString())
.isEqualTo(expectedTime);
@@ -52,7 +52,7 @@
@Test
public void testFormatElapsedTime_NoSeconds_DoNotShowSeconds() {
final double testMillis = 5 * DateUtils.MINUTE_IN_MILLIS + 30 * DateUtils.SECOND_IN_MILLIS;
- final String expectedTime = "6m";
+ final String expectedTime = "6 min";
assertThat(StringUtil.formatElapsedTime(mContext, testMillis, false).toString())
.isEqualTo(expectedTime);
@@ -62,7 +62,7 @@
public void testFormatElapsedTime_TimeMoreThanOneDay_ShowCorrectly() {
final double testMillis = 2 * DateUtils.DAY_IN_MILLIS
+ 4 * DateUtils.HOUR_IN_MILLIS + 15 * DateUtils.MINUTE_IN_MILLIS;
- final String expectedTime = "2d 4h 15m";
+ final String expectedTime = "2 days, 4 hr, 15 min";
assertThat(StringUtil.formatElapsedTime(mContext, testMillis, false).toString())
.isEqualTo(expectedTime);
@@ -71,7 +71,7 @@
@Test
public void testFormatElapsedTime_ZeroFieldsInTheMiddleDontShow() {
final double testMillis = 2 * DateUtils.DAY_IN_MILLIS + 15 * DateUtils.MINUTE_IN_MILLIS;
- final String expectedTime = "2d 15m";
+ final String expectedTime = "2 days, 15 min";
assertThat(StringUtil.formatElapsedTime(mContext, testMillis, false).toString())
.isEqualTo(expectedTime);
@@ -80,7 +80,7 @@
@Test
public void testFormatElapsedTime_FormatZero_WithSeconds() {
final double testMillis = 0;
- final String expectedTime = "0s";
+ final String expectedTime = "0 sec";
assertThat(StringUtil.formatElapsedTime(mContext, testMillis, true).toString())
.isEqualTo(expectedTime);
@@ -89,7 +89,7 @@
@Test
public void testFormatElapsedTime_FormatZero_NoSeconds() {
final double testMillis = 0;
- final String expectedTime = "0m";
+ final String expectedTime = "0 min";
assertThat(StringUtil.formatElapsedTime(mContext, testMillis, false).toString())
.isEqualTo(expectedTime);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 6d9da9b..a444ac8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1512,105 +1512,357 @@
s.dumpHistoricalOperations(p, SecureSettingsProto.HISTORICAL_OPERATIONS);
- // This uses the same order as in Settings.Secure.
+ // This uses the same order as in SecureSettingsProto.
- // Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED intentionally excluded since it's deprecated.
- // Settings.Secure.BUGREPORT_IN_POWER_MENU intentionally excluded since it's deprecated.
- // Settings.Secure.ADB_ENABLED intentionally excluded since it's deprecated.
- // Settings.Secure.ALLOW_MOCK_LOCATION intentionally excluded since it's deprecated.
+ final long accessibilityToken = p.start(SecureSettingsProto.ACCESSIBILITY);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_ENABLED,
+ SecureSettingsProto.Accessibility.ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+ SecureSettingsProto.Accessibility.ENABLED_ACCESSIBILITY_SERVICES);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED,
+ SecureSettingsProto.Accessibility.AUTOCLICK_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
+ SecureSettingsProto.Accessibility.AUTOCLICK_DELAY);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT,
+ SecureSettingsProto.Accessibility.BUTTON_TARGET_COMPONENT);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED,
+ SecureSettingsProto.Accessibility.CAPTIONING_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_CAPTIONING_LOCALE,
+ SecureSettingsProto.Accessibility.CAPTIONING_LOCALE);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_CAPTIONING_PRESET,
+ SecureSettingsProto.Accessibility.CAPTIONING_PRESET);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR,
+ SecureSettingsProto.Accessibility.CAPTIONING_BACKGROUND_COLOR);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR,
+ SecureSettingsProto.Accessibility.CAPTIONING_FOREGROUND_COLOR);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_CAPTIONING_EDGE_TYPE,
+ SecureSettingsProto.Accessibility.CAPTIONING_EDGE_TYPE);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR,
+ SecureSettingsProto.Accessibility.CAPTIONING_EDGE_COLOR);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_CAPTIONING_WINDOW_COLOR,
+ SecureSettingsProto.Accessibility.CAPTIONING_WINDOW_COLOR);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE,
+ SecureSettingsProto.Accessibility.CAPTIONING_TYPEFACE);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE,
+ SecureSettingsProto.Accessibility.CAPTIONING_FONT_SCALE);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
+ SecureSettingsProto.Accessibility.DISPLAY_DALTONIZER_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER,
+ SecureSettingsProto.Accessibility.DISPLAY_DALTONIZER);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
+ SecureSettingsProto.Accessibility.DISPLAY_INVERSION_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
+ SecureSettingsProto.Accessibility.DISPLAY_MAGNIFICATION_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
+ SecureSettingsProto.Accessibility.DISPLAY_MAGNIFICATION_NAVBAR_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+ SecureSettingsProto.Accessibility.DISPLAY_MAGNIFICATION_SCALE);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED,
+ SecureSettingsProto.Accessibility.HIGH_TEXT_CONTRAST_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON,
+ SecureSettingsProto.Accessibility.LARGE_POINTER_ICON);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED,
+ SecureSettingsProto.Accessibility.SHORTCUT_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN,
+ SecureSettingsProto.Accessibility.SHORTCUT_ON_LOCK_SCREEN);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN,
+ SecureSettingsProto.Accessibility.SHORTCUT_DIALOG_SHOWN);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
+ SecureSettingsProto.Accessibility.SHORTCUT_TARGET_SERVICE);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+ SecureSettingsProto.Accessibility.SOFT_KEYBOARD_MODE);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD,
+ SecureSettingsProto.Accessibility.SPEAK_PASSWORD);
+ dumpSetting(s, p,
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED,
+ SecureSettingsProto.Accessibility.TOUCH_EXPLORATION_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+ SecureSettingsProto.Accessibility.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
+ p.end(accessibilityToken);
+
+ dumpSetting(s, p,
+ Settings.Secure.ALLOWED_GEOLOCATION_ORIGINS,
+ SecureSettingsProto.ALLOWED_GEOLOCATION_ORIGINS);
+
+ final long aovToken = p.start(SecureSettingsProto.ALWAYS_ON_VPN);
+ dumpSetting(s, p,
+ Settings.Secure.ALWAYS_ON_VPN_APP,
+ SecureSettingsProto.AlwaysOnVpn.APP);
+ dumpSetting(s, p,
+ Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN,
+ SecureSettingsProto.AlwaysOnVpn.LOCKDOWN);
+ p.end(aovToken);
+
dumpSetting(s, p,
Settings.Secure.ANDROID_ID,
SecureSettingsProto.ANDROID_ID);
- // Settings.Secure.BLUETOOTH_ON intentionally excluded since it's deprecated.
- // Settings.Secure.DATA_ROAMING intentionally excluded since it's deprecated.
dumpSetting(s, p,
- Settings.Secure.DEFAULT_INPUT_METHOD,
- SecureSettingsProto.DEFAULT_INPUT_METHOD);
+ Settings.Secure.ANR_SHOW_BACKGROUND,
+ SecureSettingsProto.ANR_SHOW_BACKGROUND);
+
+ final long assistToken = p.start(SecureSettingsProto.ASSIST);
dumpSetting(s, p,
- Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
- SecureSettingsProto.SELECTED_INPUT_METHOD_SUBTYPE);
+ Settings.Secure.ASSISTANT,
+ SecureSettingsProto.Assist.ASSISTANT);
dumpSetting(s, p,
- Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY,
- SecureSettingsProto.INPUT_METHODS_SUBTYPE_HISTORY);
+ Settings.Secure.ASSIST_STRUCTURE_ENABLED,
+ SecureSettingsProto.Assist.STRUCTURE_ENABLED);
dumpSetting(s, p,
- Settings.Secure.INPUT_METHOD_SELECTOR_VISIBILITY,
- SecureSettingsProto.INPUT_METHOD_SELECTOR_VISIBILITY);
+ Settings.Secure.ASSIST_SCREENSHOT_ENABLED,
+ SecureSettingsProto.Assist.SCREENSHOT_ENABLED);
dumpSetting(s, p,
- Settings.Secure.VOICE_INTERACTION_SERVICE,
- SecureSettingsProto.VOICE_INTERACTION_SERVICE);
+ Settings.Secure.ASSIST_DISCLOSURE_ENABLED,
+ SecureSettingsProto.Assist.DISCLOSURE_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ASSIST_GESTURE_ENABLED,
+ SecureSettingsProto.Assist.GESTURE_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ASSIST_GESTURE_SENSITIVITY,
+ SecureSettingsProto.Assist.GESTURE_SENSITIVITY);
+ dumpSetting(s, p,
+ Settings.Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
+ SecureSettingsProto.Assist.GESTURE_SILENCE_ALERTS_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ASSIST_GESTURE_WAKE_ENABLED,
+ SecureSettingsProto.Assist.GESTURE_WAKE_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ASSIST_GESTURE_SETUP_COMPLETE,
+ SecureSettingsProto.Assist.GESTURE_SETUP_COMPLETE);
+ p.end(assistToken);
+
+ final long autofillToken = p.start(SecureSettingsProto.AUTOFILL);
dumpSetting(s, p,
Settings.Secure.AUTOFILL_SERVICE,
- SecureSettingsProto.AUTOFILL_SERVICE);
+ SecureSettingsProto.Autofill.SERVICE);
dumpSetting(s, p,
Settings.Secure.AUTOFILL_FEATURE_FIELD_CLASSIFICATION,
- SecureSettingsProto.AUTOFILL_FEATURE_FIELD_CLASSIFICATION);
+ SecureSettingsProto.Autofill.FEATURE_FIELD_CLASSIFICATION);
dumpSetting(s, p,
Settings.Secure.AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE,
- SecureSettingsProto.AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE);
+ SecureSettingsProto.Autofill.USER_DATA_MAX_USER_DATA_SIZE);
dumpSetting(s, p,
Settings.Secure.AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE,
- SecureSettingsProto.AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE);
+ SecureSettingsProto.Autofill.USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE);
dumpSetting(s, p,
Settings.Secure.AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT,
- SecureSettingsProto.AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT);
+ SecureSettingsProto.Autofill.USER_DATA_MAX_CATEGORY_COUNT);
dumpSetting(s, p,
Settings.Secure.AUTOFILL_USER_DATA_MAX_VALUE_LENGTH,
- SecureSettingsProto.AUTOFILL_USER_DATA_MAX_VALUE_LENGTH);
+ SecureSettingsProto.Autofill.USER_DATA_MAX_VALUE_LENGTH);
dumpSetting(s, p,
Settings.Secure.AUTOFILL_USER_DATA_MIN_VALUE_LENGTH,
- SecureSettingsProto.AUTOFILL_USER_DATA_MIN_VALUE_LENGTH);
- // Settings.Secure.DEVICE_PROVISIONED intentionally excluded since it's deprecated.
+ SecureSettingsProto.Autofill.USER_DATA_MIN_VALUE_LENGTH);
dumpSetting(s, p,
- Settings.Secure.USER_SETUP_COMPLETE,
- SecureSettingsProto.USER_SETUP_COMPLETE);
- // Whether the current user has been set up via setup wizard (0 = false, 1 = true). This
- // value differs from USER_SETUP_COMPLETE in that it can be reset back to 0 in case
- // SetupWizard has been re-enabled on TV devices.
+ Settings.Secure.AUTOFILL_SERVICE_SEARCH_URI,
+ SecureSettingsProto.Autofill.SERVICE_SEARCH_URI);
+ p.end(autofillToken);
+
+ final long asmToken = p.start(SecureSettingsProto.AUTOMATIC_STORAGE_MANAGER);
dumpSetting(s, p,
- Settings.Secure.TV_USER_SETUP_COMPLETE,
- SecureSettingsProto.TV_USER_SETUP_COMPLETE);
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED,
+ SecureSettingsProto.AutomaticStorageManager.ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
+ SecureSettingsProto.AutomaticStorageManager.DAYS_TO_RETAIN);
+ dumpSetting(s, p,
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED,
+ SecureSettingsProto.AutomaticStorageManager.BYTES_CLEARED);
+ dumpSetting(s, p,
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN,
+ SecureSettingsProto.AutomaticStorageManager.LAST_RUN);
+ dumpSetting(s, p,
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_TURNED_OFF_BY_POLICY,
+ SecureSettingsProto.AutomaticStorageManager.TURNED_OFF_BY_POLICY);
+ p.end(asmToken);
+
+ final long backupToken = p.start(SecureSettingsProto.BACKUP);
+ dumpSetting(s, p,
+ Settings.Secure.BACKUP_ENABLED,
+ SecureSettingsProto.Backup.ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.BACKUP_AUTO_RESTORE,
+ SecureSettingsProto.Backup.AUTO_RESTORE);
+ dumpSetting(s, p,
+ Settings.Secure.BACKUP_PROVISIONED,
+ SecureSettingsProto.Backup.PROVISIONED);
+ dumpSetting(s, p,
+ Settings.Secure.BACKUP_TRANSPORT,
+ SecureSettingsProto.Backup.TRANSPORT);
+ dumpSetting(s, p,
+ Settings.Secure.BACKUP_MANAGER_CONSTANTS,
+ SecureSettingsProto.Backup.MANAGER_CONSTANTS);
+ dumpSetting(s, p,
+ Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS,
+ SecureSettingsProto.Backup.LOCAL_TRANSPORT_PARAMETERS);
+ p.end(backupToken);
+
+ // Settings.Secure.BLUETOOTH_ON intentionally excluded since it's deprecated.
+ dumpSetting(s, p,
+ Settings.Secure.BLUETOOTH_ON_WHILE_DRIVING,
+ SecureSettingsProto.BLUETOOTH_ON_WHILE_DRIVING);
+
+ final long cameraToken = p.start(SecureSettingsProto.CAMERA);
+ dumpSetting(s, p,
+ Settings.Secure.CAMERA_GESTURE_DISABLED,
+ SecureSettingsProto.Camera.GESTURE_DISABLED);
+ dumpSetting(s, p,
+ Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED,
+ SecureSettingsProto.Camera.DOUBLE_TAP_POWER_GESTURE_DISABLED);
+ dumpSetting(s, p,
+ Settings.Secure.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED,
+ SecureSettingsProto.Camera.DOUBLE_TWIST_TO_FLIP_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.CAMERA_LIFT_TRIGGER_ENABLED,
+ SecureSettingsProto.Camera.LIFT_TRIGGER_ENABLED);
+ p.end(cameraToken);
+
+ dumpSetting(s, p,
+ Settings.Secure.CARRIER_APPS_HANDLED,
+ SecureSettingsProto.CARRIER_APPS_HANDLED);
+ dumpSetting(s, p,
+ Settings.Secure.CMAS_ADDITIONAL_BROADCAST_PKG,
+ SecureSettingsProto.CMAS_ADDITIONAL_BROADCAST_PKG);
dumpRepeatedSetting(s, p,
Settings.Secure.COMPLETED_CATEGORY_PREFIX,
SecureSettingsProto.COMPLETED_CATEGORIES);
dumpSetting(s, p,
- Settings.Secure.ENABLED_INPUT_METHODS,
- SecureSettingsProto.ENABLED_INPUT_METHODS);
+ Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS,
+ SecureSettingsProto.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS);
+ dumpSetting(s, p,
+ Settings.Secure.DEVICE_PAIRED,
+ SecureSettingsProto.DEVICE_PAIRED);
+ dumpSetting(s, p,
+ Settings.Secure.DIALER_DEFAULT_APPLICATION,
+ SecureSettingsProto.DIALER_DEFAULT_APPLICATION);
+ dumpSetting(s, p,
+ Settings.Secure.DISPLAY_DENSITY_FORCED,
+ SecureSettingsProto.DISPLAY_DENSITY_FORCED);
+ dumpSetting(s, p,
+ Settings.Secure.DOUBLE_TAP_TO_WAKE,
+ SecureSettingsProto.DOUBLE_TAP_TO_WAKE);
+
+ final long dozeToken = p.start(SecureSettingsProto.DOZE);
+ dumpSetting(s, p,
+ Settings.Secure.DOZE_ENABLED,
+ SecureSettingsProto.Doze.ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.DOZE_ALWAYS_ON,
+ SecureSettingsProto.Doze.ALWAYS_ON);
+ dumpSetting(s, p,
+ Settings.Secure.DOZE_PULSE_ON_PICK_UP,
+ SecureSettingsProto.Doze.PULSE_ON_PICK_UP);
+ dumpSetting(s, p,
+ Settings.Secure.DOZE_PULSE_ON_LONG_PRESS,
+ SecureSettingsProto.Doze.PULSE_ON_LONG_PRESS);
+ dumpSetting(s, p,
+ Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP,
+ SecureSettingsProto.Doze.PULSE_ON_DOUBLE_TAP);
+ p.end(dozeToken);
+
+ dumpSetting(s, p,
+ Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION,
+ SecureSettingsProto.EMERGENCY_ASSISTANCE_APPLICATION);
+ dumpSetting(s, p,
+ Settings.Secure.ENHANCED_VOICE_PRIVACY_ENABLED,
+ SecureSettingsProto.ENHANCED_VOICE_PRIVACY_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS,
+ SecureSettingsProto.IMMERSIVE_MODE_CONFIRMATIONS);
+
+ final long incallToken = p.start(SecureSettingsProto.INCALL);
+ dumpSetting(s, p,
+ Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
+ SecureSettingsProto.Incall.POWER_BUTTON_BEHAVIOR);
+ dumpSetting(s, p,
+ Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
+ SecureSettingsProto.Incall.BACK_BUTTON_BEHAVIOR);
+ p.end(incallToken);
+
+ final long inputMethodsToken = p.start(SecureSettingsProto.INPUT_METHODS);
+ dumpSetting(s, p,
+ Settings.Secure.DEFAULT_INPUT_METHOD,
+ SecureSettingsProto.InputMethods.DEFAULT_INPUT_METHOD);
dumpSetting(s, p,
Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS,
- SecureSettingsProto.DISABLED_SYSTEM_INPUT_METHODS);
+ SecureSettingsProto.InputMethods.DISABLED_SYSTEM_INPUT_METHODS);
+ dumpSetting(s, p,
+ Settings.Secure.ENABLED_INPUT_METHODS,
+ SecureSettingsProto.InputMethods.ENABLED_INPUT_METHODS);
+ dumpSetting(s, p,
+ Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY,
+ SecureSettingsProto.InputMethods.SUBTYPE_HISTORY);
+ dumpSetting(s, p,
+ Settings.Secure.INPUT_METHOD_SELECTOR_VISIBILITY,
+ SecureSettingsProto.InputMethods.METHOD_SELECTOR_VISIBILITY);
+ dumpSetting(s, p,
+ Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
+ SecureSettingsProto.InputMethods.SELECTED_INPUT_METHOD_SUBTYPE);
dumpSetting(s, p,
Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
- SecureSettingsProto.SHOW_IME_WITH_HARD_KEYBOARD);
- // Settings.Secure.HTTP_PROXY intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.Secure.ALWAYS_ON_VPN_APP,
- SecureSettingsProto.ALWAYS_ON_VPN_APP);
- dumpSetting(s, p,
- Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN,
- SecureSettingsProto.ALWAYS_ON_VPN_LOCKDOWN);
+ SecureSettingsProto.InputMethods.SHOW_IME_WITH_HARD_KEYBOARD);
+ p.end(inputMethodsToken);
+
dumpSetting(s, p,
Settings.Secure.INSTALL_NON_MARKET_APPS,
SecureSettingsProto.INSTALL_NON_MARKET_APPS);
dumpSetting(s, p,
- Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED,
- SecureSettingsProto.UNKNOWN_SOURCES_DEFAULT_REVERSED);
+ Settings.Secure.INSTANT_APPS_ENABLED,
+ SecureSettingsProto.INSTANT_APPS_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.KEYGUARD_SLICE_URI,
+ SecureSettingsProto.KEYGUARD_SLICE_URI);
+ dumpSetting(s, p,
+ Settings.Secure.LAST_SETUP_SHOWN,
+ SecureSettingsProto.LAST_SETUP_SHOWN);
+
+ final long locationToken = p.start(SecureSettingsProto.LOCATION);
// Settings.Secure.LOCATION_PROVIDERS_ALLOWED intentionally excluded since it's deprecated.
dumpSetting(s, p,
Settings.Secure.LOCATION_MODE,
- SecureSettingsProto.LOCATION_MODE);
+ SecureSettingsProto.Location.MODE);
dumpSetting(s, p,
Settings.Secure.LOCATION_CHANGER,
- SecureSettingsProto.LOCATION_CHANGER);
+ SecureSettingsProto.Location.CHANGER);
+ p.end(locationToken);
+
+ final long lockScreenToken = p.start(SecureSettingsProto.LOCK_SCREEN);
// Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
- SecureSettingsProto.LOCK_TO_APP_EXIT_LOCKED);
// Settings.Secure.LOCK_PATTERN_ENABLED intentionally excluded since it's deprecated.
// Settings.Secure.LOCK_PATTERN_VISIBLE intentionally excluded since it's deprecated.
// Settings.Secure.LOCK_PATTERN_TACTICLE_FEEDBACK_ENABLED intentionally excluded since it's deprecated.
dumpSetting(s, p,
Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
- SecureSettingsProto.LOCK_SCREEN_LOCK_AFTER_TIMEOUT);
+ SecureSettingsProto.LockScreen.LOCK_AFTER_TIMEOUT);
// Settings.Secure.LOCK_SCREEN_OWNER_INFO intentionally excluded since it's deprecated.
// Settings.Secure.LOCK_SCREEN_APPWIDGET_IDS intentionally excluded since it's deprecated.
// Settings.Secure.LOCK_SCREEN_FALLBACK_APPWIDGET_ID intentionally excluded since it's deprecated.
@@ -1618,162 +1870,371 @@
// Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED intentionally excluded since it's deprecated.
dumpSetting(s, p,
Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
- SecureSettingsProto.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ SecureSettingsProto.LockScreen.ALLOW_PRIVATE_NOTIFICATIONS);
dumpSetting(s, p,
Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT,
- SecureSettingsProto.LOCK_SCREEN_ALLOW_REMOTE_INPUT);
+ SecureSettingsProto.LockScreen.ALLOW_REMOTE_INPUT);
dumpSetting(s, p,
- Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING,
- SecureSettingsProto.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING);
+ Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
+ SecureSettingsProto.LockScreen.SHOW_NOTIFICATIONS);
+ p.end(lockScreenToken);
+
dumpSetting(s, p,
- Settings.Secure.TRUST_AGENTS_INITIALIZED,
- SecureSettingsProto.TRUST_AGENTS_INITIALIZED);
- // Settings.Secure.LOGGING_ID intentionally excluded since it's deprecated.
- // Settings.Secure.NETWORK_PREFERENCE intentionally excluded since it's deprecated.
+ Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
+ SecureSettingsProto.LOCK_TO_APP_EXIT_LOCKED);
dumpSetting(s, p,
- Settings.Secure.PARENTAL_CONTROL_ENABLED,
- SecureSettingsProto.PARENTAL_CONTROL_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.PARENTAL_CONTROL_LAST_UPDATE,
- SecureSettingsProto.PARENTAL_CONTROL_LAST_UPDATE);
- dumpSetting(s, p,
- Settings.Secure.PARENTAL_CONTROL_REDIRECT_URL,
- SecureSettingsProto.PARENTAL_CONTROL_REDIRECT_URL);
- dumpSetting(s, p,
- Settings.Secure.SETTINGS_CLASSNAME,
- SecureSettingsProto.SETTINGS_CLASSNAME);
- // Settings.Secure.USB_MASS_STORAGE_ENABLED intentionally excluded since it's deprecated.
- // Settings.Secure.USE_GOOGLE_MAIL intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_ENABLED,
- SecureSettingsProto.ACCESSIBILITY_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED,
- SecureSettingsProto.ACCESSIBILITY_SHORTCUT_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN,
- SecureSettingsProto.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN,
- SecureSettingsProto.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
- SecureSettingsProto.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT,
- SecureSettingsProto.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
- dumpSetting(s, p,
- Settings.Secure.TOUCH_EXPLORATION_ENABLED,
- SecureSettingsProto.TOUCH_EXPLORATION_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
- SecureSettingsProto.ENABLED_ACCESSIBILITY_SERVICES);
- dumpSetting(s, p,
- Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
- SecureSettingsProto.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
- dumpSetting(s, p,
- Settings.Secure.KEYGUARD_SLICE_URI,
- SecureSettingsProto.KEYGUARD_SLICE_URI);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD,
- SecureSettingsProto.ACCESSIBILITY_SPEAK_PASSWORD);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED,
- SecureSettingsProto.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
- SecureSettingsProto.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
- SecureSettingsProto.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
- SecureSettingsProto.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
- SecureSettingsProto.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED,
- SecureSettingsProto.ACCESSIBILITY_CAPTIONING_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_CAPTIONING_LOCALE,
- SecureSettingsProto.ACCESSIBILITY_CAPTIONING_LOCALE);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_CAPTIONING_PRESET,
- SecureSettingsProto.ACCESSIBILITY_CAPTIONING_PRESET);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR,
- SecureSettingsProto.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR,
- SecureSettingsProto.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_CAPTIONING_EDGE_TYPE,
- SecureSettingsProto.ACCESSIBILITY_CAPTIONING_EDGE_TYPE);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR,
- SecureSettingsProto.ACCESSIBILITY_CAPTIONING_EDGE_COLOR);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_CAPTIONING_WINDOW_COLOR,
- SecureSettingsProto.ACCESSIBILITY_CAPTIONING_WINDOW_COLOR);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE,
- SecureSettingsProto.ACCESSIBILITY_CAPTIONING_TYPEFACE);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE,
- SecureSettingsProto.ACCESSIBILITY_CAPTIONING_FONT_SCALE);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
- SecureSettingsProto.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
- SecureSettingsProto.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER,
- SecureSettingsProto.ACCESSIBILITY_DISPLAY_DALTONIZER);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED,
- SecureSettingsProto.ACCESSIBILITY_AUTOCLICK_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
- SecureSettingsProto.ACCESSIBILITY_AUTOCLICK_DELAY);
- dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON,
- SecureSettingsProto.ACCESSIBILITY_LARGE_POINTER_ICON);
+ Settings.Secure.LOCKDOWN_IN_POWER_MENU,
+ SecureSettingsProto.LOCKDOWN_IN_POWER_MENU);
dumpSetting(s, p,
Settings.Secure.LONG_PRESS_TIMEOUT,
SecureSettingsProto.LONG_PRESS_TIMEOUT);
+
+ final long managedProfileToken = p.start(SecureSettingsProto.MANAGED_PROFILE);
+ dumpSetting(s, p,
+ Settings.Secure.MANAGED_PROFILE_CONTACT_REMOTE_SEARCH,
+ SecureSettingsProto.ManagedProfile.CONTACT_REMOTE_SEARCH);
+ p.end(managedProfileToken);
+
+ final long mountToken = p.start(SecureSettingsProto.MOUNT);
+ dumpSetting(s, p,
+ Settings.Secure.MOUNT_PLAY_NOTIFICATION_SND,
+ SecureSettingsProto.Mount.PLAY_NOTIFICATION_SND);
+ dumpSetting(s, p,
+ Settings.Secure.MOUNT_UMS_AUTOSTART,
+ SecureSettingsProto.Mount.UMS_AUTOSTART);
+ dumpSetting(s, p,
+ Settings.Secure.MOUNT_UMS_PROMPT,
+ SecureSettingsProto.Mount.UMS_PROMPT);
+ dumpSetting(s, p,
+ Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED,
+ SecureSettingsProto.Mount.UMS_NOTIFY_ENABLED);
+ p.end(mountToken);
+
dumpSetting(s, p,
Settings.Secure.MULTI_PRESS_TIMEOUT,
SecureSettingsProto.MULTI_PRESS_TIMEOUT);
+
+ final long nfcPaymentToken = p.start(SecureSettingsProto.NFC_PAYMENT);
+ dumpSetting(s, p,
+ Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
+ SecureSettingsProto.NfcPayment.DEFAULT_COMPONENT);
+ dumpSetting(s, p,
+ Settings.Secure.NFC_PAYMENT_FOREGROUND,
+ SecureSettingsProto.NfcPayment.FOREGROUND);
+ dumpSetting(s, p,
+ Settings.Secure.PAYMENT_SERVICE_SEARCH_URI,
+ SecureSettingsProto.NfcPayment.PAYMENT_SERVICE_SEARCH_URI);
+ p.end(nfcPaymentToken);
+
+ final long nightDisplayToken = p.start(SecureSettingsProto.NIGHT_DISPLAY);
+ dumpSetting(s, p,
+ Settings.Secure.NIGHT_DISPLAY_ACTIVATED,
+ SecureSettingsProto.NightDisplay.ACTIVATED);
+ dumpSetting(s, p,
+ Settings.Secure.NIGHT_DISPLAY_AUTO_MODE,
+ SecureSettingsProto.NightDisplay.AUTO_MODE);
+ dumpSetting(s, p,
+ Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE,
+ SecureSettingsProto.NightDisplay.COLOR_TEMPERATURE);
+ dumpSetting(s, p,
+ Settings.Secure.NIGHT_DISPLAY_CUSTOM_START_TIME,
+ SecureSettingsProto.NightDisplay.CUSTOM_START_TIME);
+ dumpSetting(s, p,
+ Settings.Secure.NIGHT_DISPLAY_CUSTOM_END_TIME,
+ SecureSettingsProto.NightDisplay.CUSTOM_END_TIME);
+ dumpSetting(s, p,
+ Settings.Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
+ SecureSettingsProto.NightDisplay.LAST_ACTIVATED_TIME);
+ p.end(nightDisplayToken);
+
+ final long notificationToken = p.start(SecureSettingsProto.NOTIFICATION);
+ dumpSetting(s, p,
+ Settings.Secure.ENABLED_NOTIFICATION_ASSISTANT,
+ SecureSettingsProto.Notification.ENABLED_ASSISTANT);
+ dumpSetting(s, p,
+ Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
+ SecureSettingsProto.Notification.ENABLED_LISTENERS);
+ dumpSetting(s, p,
+ Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
+ SecureSettingsProto.Notification.ENABLED_POLICY_ACCESS_PACKAGES);
+ dumpSetting(s, p,
+ Settings.Secure.NOTIFICATION_BADGING,
+ SecureSettingsProto.Notification.BADGING);
+ dumpSetting(s, p,
+ Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING,
+ SecureSettingsProto.Notification.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING);
+ p.end(notificationToken);
+
+ final long packageVerifierToken = p.start(SecureSettingsProto.PACKAGE_VERIFIER);
+ dumpSetting(s, p,
+ Settings.Secure.PACKAGE_VERIFIER_USER_CONSENT,
+ SecureSettingsProto.PackageVerifier.USER_CONSENT);
+ dumpSetting(s, p,
+ Settings.Secure.PACKAGE_VERIFIER_STATE,
+ SecureSettingsProto.PackageVerifier.STATE);
+ p.end(packageVerifierToken);
+
+ final long parentalControlToken = p.start(SecureSettingsProto.PARENTAL_CONTROL);
+ dumpSetting(s, p,
+ Settings.Secure.PARENTAL_CONTROL_ENABLED,
+ SecureSettingsProto.ParentalControl.ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.PARENTAL_CONTROL_LAST_UPDATE,
+ SecureSettingsProto.ParentalControl.LAST_UPDATE);
+ dumpSetting(s, p,
+ Settings.Secure.PARENTAL_CONTROL_REDIRECT_URL,
+ SecureSettingsProto.ParentalControl.REDIRECT_URL);
+ p.end(parentalControlToken);
+
+ final long printServiceToken = p.start(SecureSettingsProto.PRINT_SERVICE);
+ dumpSetting(s, p,
+ Settings.Secure.PRINT_SERVICE_SEARCH_URI,
+ SecureSettingsProto.PrintService.SEARCH_URI);
dumpSetting(s, p,
Settings.Secure.ENABLED_PRINT_SERVICES,
- SecureSettingsProto.ENABLED_PRINT_SERVICES);
+ SecureSettingsProto.PrintService.ENABLED_PRINT_SERVICES);
dumpSetting(s, p,
Settings.Secure.DISABLED_PRINT_SERVICES,
- SecureSettingsProto.DISABLED_PRINT_SERVICES);
+ SecureSettingsProto.PrintService.DISABLED_PRINT_SERVICES);
+ p.end(printServiceToken);
+
+ final long qsToken = p.start(SecureSettingsProto.QS);
dumpSetting(s, p,
- Settings.Secure.DISPLAY_DENSITY_FORCED,
- SecureSettingsProto.DISPLAY_DENSITY_FORCED);
+ Settings.Secure.QS_TILES,
+ SecureSettingsProto.QuickSettings.TILES);
+ dumpSetting(s, p,
+ Settings.Secure.QS_AUTO_ADDED_TILES,
+ SecureSettingsProto.QuickSettings.AUTO_ADDED_TILES);
+ p.end(qsToken);
+
+ final long rotationToken = p.start(SecureSettingsProto.ROTATION);
+ dumpSetting(s, p,
+ Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
+ SecureSettingsProto.Rotation.SHOW_ROTATION_SUGGESTIONS);
+ dumpSetting(s, p,
+ Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED,
+ SecureSettingsProto.Rotation.NUM_ROTATION_SUGGESTIONS_ACCEPTED);
+ p.end(rotationToken);
+
+ final long screensaverToken = p.start(SecureSettingsProto.SCREENSAVER);
+ dumpSetting(s, p,
+ Settings.Secure.SCREENSAVER_ENABLED,
+ SecureSettingsProto.Screensaver.ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.SCREENSAVER_COMPONENTS,
+ SecureSettingsProto.Screensaver.COMPONENTS);
+ dumpSetting(s, p,
+ Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
+ SecureSettingsProto.Screensaver.ACTIVATE_ON_DOCK);
+ dumpSetting(s, p,
+ Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
+ SecureSettingsProto.Screensaver.ACTIVATE_ON_SLEEP);
+ dumpSetting(s, p,
+ Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
+ SecureSettingsProto.Screensaver.DEFAULT_COMPONENT);
+ p.end(screensaverToken);
+
+ final long searchToken = p.start(SecureSettingsProto.SEARCH);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY,
+ SecureSettingsProto.Search.GLOBAL_SEARCH_ACTIVITY);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_NUM_PROMOTED_SOURCES,
+ SecureSettingsProto.Search.NUM_PROMOTED_SOURCES);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_MAX_RESULTS_TO_DISPLAY,
+ SecureSettingsProto.Search.MAX_RESULTS_TO_DISPLAY);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_MAX_RESULTS_PER_SOURCE,
+ SecureSettingsProto.Search.MAX_RESULTS_PER_SOURCE);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_WEB_RESULTS_OVERRIDE_LIMIT,
+ SecureSettingsProto.Search.WEB_RESULTS_OVERRIDE_LIMIT);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_PROMOTED_SOURCE_DEADLINE_MILLIS,
+ SecureSettingsProto.Search.PROMOTED_SOURCE_DEADLINE_MILLIS);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_SOURCE_TIMEOUT_MILLIS,
+ SecureSettingsProto.Search.SOURCE_TIMEOUT_MILLIS);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_PREFILL_MILLIS,
+ SecureSettingsProto.Search.PREFILL_MILLIS);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_MAX_STAT_AGE_MILLIS,
+ SecureSettingsProto.Search.MAX_STAT_AGE_MILLIS);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_MAX_SOURCE_EVENT_AGE_MILLIS,
+ SecureSettingsProto.Search.MAX_SOURCE_EVENT_AGE_MILLIS);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_MIN_IMPRESSIONS_FOR_SOURCE_RANKING,
+ SecureSettingsProto.Search.MIN_IMPRESSIONS_FOR_SOURCE_RANKING);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_MIN_CLICKS_FOR_SOURCE_RANKING,
+ SecureSettingsProto.Search.MIN_CLICKS_FOR_SOURCE_RANKING);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_MAX_SHORTCUTS_RETURNED,
+ SecureSettingsProto.Search.MAX_SHORTCUTS_RETURNED);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_QUERY_THREAD_CORE_POOL_SIZE,
+ SecureSettingsProto.Search.QUERY_THREAD_CORE_POOL_SIZE);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_QUERY_THREAD_MAX_POOL_SIZE,
+ SecureSettingsProto.Search.QUERY_THREAD_MAX_POOL_SIZE);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_SHORTCUT_REFRESH_CORE_POOL_SIZE,
+ SecureSettingsProto.Search.SHORTCUT_REFRESH_CORE_POOL_SIZE);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_SHORTCUT_REFRESH_MAX_POOL_SIZE,
+ SecureSettingsProto.Search.SHORTCUT_REFRESH_MAX_POOL_SIZE);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_THREAD_KEEPALIVE_SECONDS,
+ SecureSettingsProto.Search.THREAD_KEEPALIVE_SECONDS);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_PER_SOURCE_CONCURRENT_QUERY_LIMIT,
+ SecureSettingsProto.Search.PER_SOURCE_CONCURRENT_QUERY_LIMIT);
+ p.end(searchToken);
+
+ final long spellCheckerToken = p.start(SecureSettingsProto.SPELL_CHECKER);
+ dumpSetting(s, p,
+ Settings.Secure.SPELL_CHECKER_ENABLED,
+ SecureSettingsProto.SpellChecker.ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.SELECTED_SPELL_CHECKER,
+ SecureSettingsProto.SpellChecker.SELECTED);
+ dumpSetting(s, p,
+ Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE,
+ SecureSettingsProto.SpellChecker.SELECTED_SUBTYPE);
+ p.end(spellCheckerToken);
+
+ dumpSetting(s, p,
+ Settings.Secure.SETTINGS_CLASSNAME,
+ SecureSettingsProto.SETTINGS_CLASSNAME);
+ dumpSetting(s, p,
+ Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
+ SecureSettingsProto.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION);
+ dumpSetting(s, p,
+ Settings.Secure.SKIP_FIRST_USE_HINTS,
+ SecureSettingsProto.SKIP_FIRST_USE_HINTS);
+ dumpSetting(s, p,
+ Settings.Secure.SLEEP_TIMEOUT,
+ SecureSettingsProto.SLEEP_TIMEOUT);
+ dumpSetting(s, p,
+ Settings.Secure.SMS_DEFAULT_APPLICATION,
+ SecureSettingsProto.SMS_DEFAULT_APPLICATION);
+ dumpSetting(s, p,
+ Settings.Secure.SYNC_PARENT_SOUNDS,
+ SecureSettingsProto.SYNC_PARENT_SOUNDS);
+ dumpSetting(s, p,
+ Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED,
+ SecureSettingsProto.SYSTEM_NAVIGATION_KEYS_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.TRUST_AGENTS_INITIALIZED,
+ SecureSettingsProto.TRUST_AGENTS_INITIALIZED);
+
+ final long ttsToken = p.start(SecureSettingsProto.TTS);
// Settings.Secure.TTS_USE_DEFAULTS intentionally excluded since it's deprecated.
dumpSetting(s, p,
Settings.Secure.TTS_DEFAULT_RATE,
- SecureSettingsProto.TTS_DEFAULT_RATE);
+ SecureSettingsProto.Tts.DEFAULT_RATE);
dumpSetting(s, p,
Settings.Secure.TTS_DEFAULT_PITCH,
- SecureSettingsProto.TTS_DEFAULT_PITCH);
+ SecureSettingsProto.Tts.DEFAULT_PITCH);
dumpSetting(s, p,
Settings.Secure.TTS_DEFAULT_SYNTH,
- SecureSettingsProto.TTS_DEFAULT_SYNTH);
+ SecureSettingsProto.Tts.DEFAULT_SYNTH);
// Settings.Secure.TTS_DEFAULT_LANG intentionally excluded since it's deprecated.
// Settings.Secure.TTS_DEFAULT_COUNTRY intentionally excluded since it's deprecated.
// Settings.Secure.TTS_DEFAULT_VARIANT intentionally excluded since it's deprecated.
dumpSetting(s, p,
Settings.Secure.TTS_DEFAULT_LOCALE,
- SecureSettingsProto.TTS_DEFAULT_LOCALE);
+ SecureSettingsProto.Tts.DEFAULT_LOCALE);
dumpSetting(s, p,
Settings.Secure.TTS_ENABLED_PLUGINS,
- SecureSettingsProto.TTS_ENABLED_PLUGINS);
+ SecureSettingsProto.Tts.ENABLED_PLUGINS);
+ p.end(ttsToken);
+
+ final long ttyToken = p.start(SecureSettingsProto.TTY);
+ dumpSetting(s, p,
+ Settings.Secure.TTY_MODE_ENABLED,
+ SecureSettingsProto.Tty.TTY_MODE_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.PREFERRED_TTY_MODE,
+ SecureSettingsProto.Tty.PREFERRED_TTY_MODE);
+ p.end(ttyToken);
+
+ final long tvToken = p.start(SecureSettingsProto.TV);
+ // Whether the current user has been set up via setup wizard (0 = false, 1 = true). This
+ // value differs from USER_SETUP_COMPLETE in that it can be reset back to 0 in case
+ // SetupWizard has been re-enabled on TV devices.
+ dumpSetting(s, p,
+ Settings.Secure.TV_USER_SETUP_COMPLETE,
+ SecureSettingsProto.Tv.USER_SETUP_COMPLETE);
+ dumpSetting(s, p,
+ Settings.Secure.TV_INPUT_HIDDEN_INPUTS,
+ SecureSettingsProto.Tv.INPUT_HIDDEN_INPUTS);
+ dumpSetting(s, p,
+ Settings.Secure.TV_INPUT_CUSTOM_LABELS,
+ SecureSettingsProto.Tv.INPUT_CUSTOM_LABELS);
+ p.end(tvToken);
+
+ dumpSetting(s, p,
+ Settings.Secure.UI_NIGHT_MODE,
+ SecureSettingsProto.UI_NIGHT_MODE);
+ dumpSetting(s, p,
+ Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED,
+ SecureSettingsProto.UNKNOWN_SOURCES_DEFAULT_REVERSED);
+ dumpSetting(s, p,
+ Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED,
+ SecureSettingsProto.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED);
+ dumpSetting(s, p,
+ Settings.Secure.USER_SETUP_COMPLETE,
+ SecureSettingsProto.USER_SETUP_COMPLETE);
+
+ final long voiceToken = p.start(SecureSettingsProto.VOICE);
+ dumpSetting(s, p,
+ Settings.Secure.VOICE_INTERACTION_SERVICE,
+ SecureSettingsProto.Voice.INTERACTION_SERVICE);
+ dumpSetting(s, p,
+ Settings.Secure.VOICE_RECOGNITION_SERVICE,
+ SecureSettingsProto.Voice.RECOGNITION_SERVICE);
+ p.end(voiceToken);
+
+ final long volumeToken = p.start(SecureSettingsProto.VOLUME);
+ dumpSetting(s, p,
+ Settings.Secure.VOLUME_HUSH_GESTURE,
+ SecureSettingsProto.Volume.HUSH_GESTURE);
+ dumpSetting(s, p,
+ Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS,
+ SecureSettingsProto.Volume.UNSAFE_VOLUME_MUSIC_ACTIVE_MS);
+ p.end(volumeToken);
+
+ final long vrToken = p.start(SecureSettingsProto.VR);
+ dumpSetting(s, p,
+ Settings.Secure.VR_DISPLAY_MODE,
+ SecureSettingsProto.Vr.DISPLAY_MODE);
+ dumpSetting(s, p,
+ Settings.Secure.ENABLED_VR_LISTENERS,
+ SecureSettingsProto.Vr.ENABLED_LISTENERS);
+ p.end(vrToken);
+
+ dumpSetting(s, p,
+ Settings.Secure.WAKE_GESTURE_ENABLED,
+ SecureSettingsProto.WAKE_GESTURE_ENABLED);
+
+ // Please insert new settings using the same order as in SecureSettingsProto.
+ p.end(token);
+
+ // Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED intentionally excluded since it's deprecated.
+ // Settings.Secure.BUGREPORT_IN_POWER_MENU intentionally excluded since it's deprecated.
+ // Settings.Secure.ADB_ENABLED intentionally excluded since it's deprecated.
+ // Settings.Secure.ALLOW_MOCK_LOCATION intentionally excluded since it's deprecated.
+ // Settings.Secure.DATA_ROAMING intentionally excluded since it's deprecated.
+ // Settings.Secure.DEVICE_PROVISIONED intentionally excluded since it's deprecated.
+ // Settings.Secure.HTTP_PROXY intentionally excluded since it's deprecated.
+ // Settings.Secure.LOGGING_ID intentionally excluded since it's deprecated.
+ // Settings.Secure.NETWORK_PREFERENCE intentionally excluded since it's deprecated.
+ // Settings.Secure.USB_MASS_STORAGE_ENABLED intentionally excluded since it's deprecated.
+ // Settings.Secure.USE_GOOGLE_MAIL intentionally excluded since it's deprecated.
// Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON intentionally excluded since it's deprecated.
// Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY intentionally excluded since it's deprecated.
// Settings.Secure.WIFI_NUM_OPEN_NETWORKS_KEPT intentionally excluded since it's deprecated.
@@ -1792,365 +2253,11 @@
// Settings.Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS intentionally excluded since it's deprecated.
// Settings.Secure.WIFI_MAX_DHCP_RETRY_COUNT intentionally excluded since it's deprecated.
// Settings.Secure.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS,
- SecureSettingsProto.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS);
// Settings.Secure.BACKGROUND_DATA intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.Secure.ALLOWED_GEOLOCATION_ORIGINS,
- SecureSettingsProto.ALLOWED_GEOLOCATION_ORIGINS);
- dumpSetting(s, p,
- Settings.Secure.PREFERRED_TTY_MODE,
- SecureSettingsProto.PREFERRED_TTY_MODE);
- dumpSetting(s, p,
- Settings.Secure.ENHANCED_VOICE_PRIVACY_ENABLED,
- SecureSettingsProto.ENHANCED_VOICE_PRIVACY_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.TTY_MODE_ENABLED,
- SecureSettingsProto.TTY_MODE_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.BACKUP_ENABLED,
- SecureSettingsProto.BACKUP_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.BACKUP_AUTO_RESTORE,
- SecureSettingsProto.BACKUP_AUTO_RESTORE);
- dumpSetting(s, p,
- Settings.Secure.BACKUP_PROVISIONED,
- SecureSettingsProto.BACKUP_PROVISIONED);
- dumpSetting(s, p,
- Settings.Secure.BACKUP_TRANSPORT,
- SecureSettingsProto.BACKUP_TRANSPORT);
- dumpSetting(s, p,
- Settings.Secure.LAST_SETUP_SHOWN,
- SecureSettingsProto.LAST_SETUP_SHOWN);
// Settings.Secure.WIFI_IDLE_MS intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY,
- SecureSettingsProto.SEARCH_GLOBAL_SEARCH_ACTIVITY);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_NUM_PROMOTED_SOURCES,
- SecureSettingsProto.SEARCH_NUM_PROMOTED_SOURCES);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_MAX_RESULTS_TO_DISPLAY,
- SecureSettingsProto.SEARCH_MAX_RESULTS_TO_DISPLAY);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_MAX_RESULTS_PER_SOURCE,
- SecureSettingsProto.SEARCH_MAX_RESULTS_PER_SOURCE);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_WEB_RESULTS_OVERRIDE_LIMIT,
- SecureSettingsProto.SEARCH_WEB_RESULTS_OVERRIDE_LIMIT);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_PROMOTED_SOURCE_DEADLINE_MILLIS,
- SecureSettingsProto.SEARCH_PROMOTED_SOURCE_DEADLINE_MILLIS);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_SOURCE_TIMEOUT_MILLIS,
- SecureSettingsProto.SEARCH_SOURCE_TIMEOUT_MILLIS);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_PREFILL_MILLIS,
- SecureSettingsProto.SEARCH_PREFILL_MILLIS);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_MAX_STAT_AGE_MILLIS,
- SecureSettingsProto.SEARCH_MAX_STAT_AGE_MILLIS);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_MAX_SOURCE_EVENT_AGE_MILLIS,
- SecureSettingsProto.SEARCH_MAX_SOURCE_EVENT_AGE_MILLIS);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_MIN_IMPRESSIONS_FOR_SOURCE_RANKING,
- SecureSettingsProto.SEARCH_MIN_IMPRESSIONS_FOR_SOURCE_RANKING);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_MIN_CLICKS_FOR_SOURCE_RANKING,
- SecureSettingsProto.SEARCH_MIN_CLICKS_FOR_SOURCE_RANKING);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_MAX_SHORTCUTS_RETURNED,
- SecureSettingsProto.SEARCH_MAX_SHORTCUTS_RETURNED);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_QUERY_THREAD_CORE_POOL_SIZE,
- SecureSettingsProto.SEARCH_QUERY_THREAD_CORE_POOL_SIZE);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_QUERY_THREAD_MAX_POOL_SIZE,
- SecureSettingsProto.SEARCH_QUERY_THREAD_MAX_POOL_SIZE);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_SHORTCUT_REFRESH_CORE_POOL_SIZE,
- SecureSettingsProto.SEARCH_SHORTCUT_REFRESH_CORE_POOL_SIZE);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_SHORTCUT_REFRESH_MAX_POOL_SIZE,
- SecureSettingsProto.SEARCH_SHORTCUT_REFRESH_MAX_POOL_SIZE);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_THREAD_KEEPALIVE_SECONDS,
- SecureSettingsProto.SEARCH_THREAD_KEEPALIVE_SECONDS);
- dumpSetting(s, p,
- Settings.Secure.SEARCH_PER_SOURCE_CONCURRENT_QUERY_LIMIT,
- SecureSettingsProto.SEARCH_PER_SOURCE_CONCURRENT_QUERY_LIMIT);
- dumpSetting(s, p,
- Settings.Secure.MOUNT_PLAY_NOTIFICATION_SND,
- SecureSettingsProto.MOUNT_PLAY_NOTIFICATION_SND);
- dumpSetting(s, p,
- Settings.Secure.MOUNT_UMS_AUTOSTART,
- SecureSettingsProto.MOUNT_UMS_AUTOSTART);
- dumpSetting(s, p,
- Settings.Secure.MOUNT_UMS_PROMPT,
- SecureSettingsProto.MOUNT_UMS_PROMPT);
- dumpSetting(s, p,
- Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED,
- SecureSettingsProto.MOUNT_UMS_NOTIFY_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ANR_SHOW_BACKGROUND,
- SecureSettingsProto.ANR_SHOW_BACKGROUND);
- dumpSetting(s, p,
- Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
- SecureSettingsProto.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION);
- dumpSetting(s, p,
- Settings.Secure.VOICE_RECOGNITION_SERVICE,
- SecureSettingsProto.VOICE_RECOGNITION_SERVICE);
- dumpSetting(s, p,
- Settings.Secure.PACKAGE_VERIFIER_USER_CONSENT,
- SecureSettingsProto.PACKAGE_VERIFIER_USER_CONSENT);
- dumpSetting(s, p,
- Settings.Secure.SELECTED_SPELL_CHECKER,
- SecureSettingsProto.SELECTED_SPELL_CHECKER);
- dumpSetting(s, p,
- Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE,
- SecureSettingsProto.SELECTED_SPELL_CHECKER_SUBTYPE);
- dumpSetting(s, p,
- Settings.Secure.SPELL_CHECKER_ENABLED,
- SecureSettingsProto.SPELL_CHECKER_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
- SecureSettingsProto.INCALL_POWER_BUTTON_BEHAVIOR);
- dumpSetting(s, p,
- Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
- SecureSettingsProto.INCALL_BACK_BUTTON_BEHAVIOR);
- dumpSetting(s, p,
- Settings.Secure.WAKE_GESTURE_ENABLED,
- SecureSettingsProto.WAKE_GESTURE_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.DOZE_ENABLED,
- SecureSettingsProto.DOZE_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.DOZE_ALWAYS_ON,
- SecureSettingsProto.DOZE_ALWAYS_ON);
- dumpSetting(s, p,
- Settings.Secure.DOZE_PULSE_ON_PICK_UP,
- SecureSettingsProto.DOZE_PULSE_ON_PICK_UP);
- dumpSetting(s, p,
- Settings.Secure.DOZE_PULSE_ON_LONG_PRESS,
- SecureSettingsProto.DOZE_PULSE_ON_LONG_PRESS);
- dumpSetting(s, p,
- Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP,
- SecureSettingsProto.DOZE_PULSE_ON_DOUBLE_TAP);
- dumpSetting(s, p,
- Settings.Secure.UI_NIGHT_MODE,
- SecureSettingsProto.UI_NIGHT_MODE);
- dumpSetting(s, p,
- Settings.Secure.SCREENSAVER_ENABLED,
- SecureSettingsProto.SCREENSAVER_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.SCREENSAVER_COMPONENTS,
- SecureSettingsProto.SCREENSAVER_COMPONENTS);
- dumpSetting(s, p,
- Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
- SecureSettingsProto.SCREENSAVER_ACTIVATE_ON_DOCK);
- dumpSetting(s, p,
- Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
- SecureSettingsProto.SCREENSAVER_ACTIVATE_ON_SLEEP);
- dumpSetting(s, p,
- Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
- SecureSettingsProto.SCREENSAVER_DEFAULT_COMPONENT);
- dumpSetting(s, p,
- Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
- SecureSettingsProto.NFC_PAYMENT_DEFAULT_COMPONENT);
- dumpSetting(s, p,
- Settings.Secure.NFC_PAYMENT_FOREGROUND,
- SecureSettingsProto.NFC_PAYMENT_FOREGROUND);
- dumpSetting(s, p,
- Settings.Secure.SMS_DEFAULT_APPLICATION,
- SecureSettingsProto.SMS_DEFAULT_APPLICATION);
- dumpSetting(s, p,
- Settings.Secure.DIALER_DEFAULT_APPLICATION,
- SecureSettingsProto.DIALER_DEFAULT_APPLICATION);
- dumpSetting(s, p,
- Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION,
- SecureSettingsProto.EMERGENCY_ASSISTANCE_APPLICATION);
- dumpSetting(s, p,
- Settings.Secure.ASSIST_STRUCTURE_ENABLED,
- SecureSettingsProto.ASSIST_STRUCTURE_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ASSIST_SCREENSHOT_ENABLED,
- SecureSettingsProto.ASSIST_SCREENSHOT_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ASSIST_DISCLOSURE_ENABLED,
- SecureSettingsProto.ASSIST_DISCLOSURE_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
- SecureSettingsProto.SHOW_ROTATION_SUGGESTIONS);
- dumpSetting(s, p,
- Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED,
- SecureSettingsProto.NUM_ROTATION_SUGGESTIONS_ACCEPTED);
- dumpSetting(s, p,
- Settings.Secure.ENABLED_NOTIFICATION_ASSISTANT,
- SecureSettingsProto.ENABLED_NOTIFICATION_ASSISTANT);
- dumpSetting(s, p,
- Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
- SecureSettingsProto.ENABLED_NOTIFICATION_LISTENERS);
- dumpSetting(s, p,
- Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
- SecureSettingsProto.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
- dumpSetting(s, p,
- Settings.Secure.SYNC_PARENT_SOUNDS,
- SecureSettingsProto.SYNC_PARENT_SOUNDS);
- dumpSetting(s, p,
- Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS,
- SecureSettingsProto.IMMERSIVE_MODE_CONFIRMATIONS);
- dumpSetting(s, p,
- Settings.Secure.PRINT_SERVICE_SEARCH_URI,
- SecureSettingsProto.PRINT_SERVICE_SEARCH_URI);
- dumpSetting(s, p,
- Settings.Secure.PAYMENT_SERVICE_SEARCH_URI,
- SecureSettingsProto.PAYMENT_SERVICE_SEARCH_URI);
- dumpSetting(s, p,
- Settings.Secure.AUTOFILL_SERVICE_SEARCH_URI,
- SecureSettingsProto.AUTOFILL_SERVICE_SEARCH_URI);
- dumpSetting(s, p,
- Settings.Secure.SKIP_FIRST_USE_HINTS,
- SecureSettingsProto.SKIP_FIRST_USE_HINTS);
- dumpSetting(s, p,
- Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS,
- SecureSettingsProto.UNSAFE_VOLUME_MUSIC_ACTIVE_MS);
- dumpSetting(s, p,
- Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
- SecureSettingsProto.LOCK_SCREEN_SHOW_NOTIFICATIONS);
- dumpSetting(s, p,
- Settings.Secure.TV_INPUT_HIDDEN_INPUTS,
- SecureSettingsProto.TV_INPUT_HIDDEN_INPUTS);
- dumpSetting(s, p,
- Settings.Secure.TV_INPUT_CUSTOM_LABELS,
- SecureSettingsProto.TV_INPUT_CUSTOM_LABELS);
- dumpSetting(s, p,
- Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED,
- SecureSettingsProto.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED);
- dumpSetting(s, p,
- Settings.Secure.SLEEP_TIMEOUT,
- SecureSettingsProto.SLEEP_TIMEOUT);
- dumpSetting(s, p,
- Settings.Secure.DOUBLE_TAP_TO_WAKE,
- SecureSettingsProto.DOUBLE_TAP_TO_WAKE);
- dumpSetting(s, p,
- Settings.Secure.ASSISTANT,
- SecureSettingsProto.ASSISTANT);
- dumpSetting(s, p,
- Settings.Secure.CAMERA_GESTURE_DISABLED,
- SecureSettingsProto.CAMERA_GESTURE_DISABLED);
- dumpSetting(s, p,
- Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED,
- SecureSettingsProto.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED);
- dumpSetting(s, p,
- Settings.Secure.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED,
- SecureSettingsProto.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.CAMERA_LIFT_TRIGGER_ENABLED,
- SecureSettingsProto.CAMERA_LIFT_TRIGGER_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ASSIST_GESTURE_ENABLED,
- SecureSettingsProto.ASSIST_GESTURE_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ASSIST_GESTURE_SENSITIVITY,
- SecureSettingsProto.ASSIST_GESTURE_SENSITIVITY);
- dumpSetting(s, p,
- Settings.Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
- SecureSettingsProto.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ASSIST_GESTURE_WAKE_ENABLED,
- SecureSettingsProto.ASSIST_GESTURE_WAKE_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.ASSIST_GESTURE_SETUP_COMPLETE,
- SecureSettingsProto.ASSIST_GESTURE_SETUP_COMPLETE);
- dumpSetting(s, p,
- Settings.Secure.NIGHT_DISPLAY_ACTIVATED,
- SecureSettingsProto.NIGHT_DISPLAY_ACTIVATED);
- dumpSetting(s, p,
- Settings.Secure.NIGHT_DISPLAY_AUTO_MODE,
- SecureSettingsProto.NIGHT_DISPLAY_AUTO_MODE);
- dumpSetting(s, p,
- Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE,
- SecureSettingsProto.NIGHT_DISPLAY_COLOR_TEMPERATURE);
- dumpSetting(s, p,
- Settings.Secure.NIGHT_DISPLAY_CUSTOM_START_TIME,
- SecureSettingsProto.NIGHT_DISPLAY_CUSTOM_START_TIME);
- dumpSetting(s, p,
- Settings.Secure.NIGHT_DISPLAY_CUSTOM_END_TIME,
- SecureSettingsProto.NIGHT_DISPLAY_CUSTOM_END_TIME);
- dumpSetting(s, p,
- Settings.Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
- SecureSettingsProto.NIGHT_DISPLAY_LAST_ACTIVATED_TIME);
- dumpSetting(s, p,
- Settings.Secure.ENABLED_VR_LISTENERS,
- SecureSettingsProto.ENABLED_VR_LISTENERS);
- dumpSetting(s, p,
- Settings.Secure.VR_DISPLAY_MODE,
- SecureSettingsProto.VR_DISPLAY_MODE);
- dumpSetting(s, p,
- Settings.Secure.CARRIER_APPS_HANDLED,
- SecureSettingsProto.CARRIER_APPS_HANDLED);
- dumpSetting(s, p,
- Settings.Secure.MANAGED_PROFILE_CONTACT_REMOTE_SEARCH,
- SecureSettingsProto.MANAGED_PROFILE_CONTACT_REMOTE_SEARCH);
- dumpSetting(s, p,
- Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED,
- SecureSettingsProto.AUTOMATIC_STORAGE_MANAGER_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
- SecureSettingsProto.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN);
- dumpSetting(s, p,
- Settings.Secure.AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED,
- SecureSettingsProto.AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED);
- dumpSetting(s, p,
- Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN,
- SecureSettingsProto.AUTOMATIC_STORAGE_MANAGER_LAST_RUN);
- dumpSetting(s, p,
- Settings.Secure.AUTOMATIC_STORAGE_MANAGER_TURNED_OFF_BY_POLICY,
- SecureSettingsProto.AUTOMATIC_STORAGE_MANAGER_TURNED_OFF_BY_POLICY);
- dumpSetting(s, p,
- Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED,
- SecureSettingsProto.SYSTEM_NAVIGATION_KEYS_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.QS_TILES,
- SecureSettingsProto.QS_TILES);
- dumpSetting(s, p,
- Settings.Secure.INSTANT_APPS_ENABLED,
- SecureSettingsProto.INSTANT_APPS_ENABLED);
- dumpSetting(s, p,
- Settings.Secure.DEVICE_PAIRED,
- SecureSettingsProto.DEVICE_PAIRED);
- dumpSetting(s, p,
- Settings.Secure.PACKAGE_VERIFIER_STATE,
- SecureSettingsProto.PACKAGE_VERIFIER_STATE);
- dumpSetting(s, p,
- Settings.Secure.CMAS_ADDITIONAL_BROADCAST_PKG,
- SecureSettingsProto.CMAS_ADDITIONAL_BROADCAST_PKG);
- dumpSetting(s, p,
- Settings.Secure.NOTIFICATION_BADGING,
- SecureSettingsProto.NOTIFICATION_BADGING);
- dumpSetting(s, p,
- Settings.Secure.QS_AUTO_ADDED_TILES,
- SecureSettingsProto.QS_AUTO_ADDED_TILES);
- dumpSetting(s, p,
- Settings.Secure.LOCKDOWN_IN_POWER_MENU,
- SecureSettingsProto.LOCKDOWN_IN_POWER_MENU);
- dumpSetting(s, p,
- Settings.Secure.BACKUP_MANAGER_CONSTANTS,
- SecureSettingsProto.BACKUP_MANAGER_CONSTANTS);
- dumpSetting(s, p,
- Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS,
- SecureSettingsProto.BACKUP_LOCAL_TRANSPORT_PARAMETERS);
- dumpSetting(s, p,
- Settings.Secure.BLUETOOTH_ON_WHILE_DRIVING,
- SecureSettingsProto.BLUETOOTH_ON_WHILE_DRIVING);
- dumpSetting(s, p,
- Settings.Secure.VOLUME_HUSH_GESTURE,
- SecureSettingsProto.VOLUME_HUSH_GESTURE);
- // Please insert new settings using the same order as in Settings.Secure.
- p.end(token);
+
+ // Please insert new settings using the same order as in SecureSettingsProto.
}
private static void dumpProtoSystemSettingsLocked(
@@ -2159,15 +2266,293 @@
s.dumpHistoricalOperations(p, SystemSettingsProto.HISTORICAL_OPERATIONS);
- // This uses the same order as in Settings.System.
+ // This uses the same order as in SystemSettingsProto.
- // Settings.System.STAY_ON_WHILE_PLUGGED_IN intentionally excluded since it's deprecated.
+ dumpSetting(s, p,
+ Settings.System.ADVANCED_SETTINGS,
+ SystemSettingsProto.ADVANCED_SETTINGS);
+
+ final long alarmToken = p.start(SystemSettingsProto.ALARM);
+ dumpSetting(s, p,
+ Settings.System.ALARM_ALERT,
+ SystemSettingsProto.Alarm.DEFAULT_URI);
+ dumpSetting(s, p,
+ Settings.System.ALARM_ALERT_CACHE,
+ SystemSettingsProto.Alarm.ALERT_CACHE);
+ // Settings.System.NEXT_ALARM_FORMATTED intentionally excluded since it's deprecated.
+ p.end(alarmToken);
+
+ final long bluetoothToken = p.start(SystemSettingsProto.BLUETOOTH);
+ dumpSetting(s, p,
+ Settings.System.BLUETOOTH_DISCOVERABILITY,
+ SystemSettingsProto.Bluetooth.DISCOVERABILITY);
+ dumpSetting(s, p,
+ Settings.System.BLUETOOTH_DISCOVERABILITY_TIMEOUT,
+ SystemSettingsProto.Bluetooth.DISCOVERABILITY_TIMEOUT_SECS);
+ p.end(bluetoothToken);
+
+ dumpSetting(s, p,
+ Settings.System.DATE_FORMAT,
+ SystemSettingsProto.DATE_FORMAT);
+ dumpSetting(s, p,
+ Settings.System.DISPLAY_COLOR_MODE,
+ SystemSettingsProto.DISPLAY_COLOR_MODE);
+
+ final long devOptionsToken = p.start(SystemSettingsProto.DEVELOPER_OPTIONS);
+ dumpSetting(s, p,
+ Settings.System.SHOW_TOUCHES,
+ SystemSettingsProto.DevOptions.SHOW_TOUCHES);
+ dumpSetting(s, p,
+ Settings.System.POINTER_LOCATION,
+ SystemSettingsProto.DevOptions.POINTER_LOCATION);
+ dumpSetting(s, p,
+ Settings.System.WINDOW_ORIENTATION_LISTENER_LOG,
+ SystemSettingsProto.DevOptions.WINDOW_ORIENTATION_LISTENER_LOG);
+ p.end(devOptionsToken);
+
+ final long dtmfToneToken = p.start(SystemSettingsProto.DTMF_TONE);
+ dumpSetting(s, p,
+ Settings.System.DTMF_TONE_WHEN_DIALING,
+ SystemSettingsProto.DtmfTone.PLAY_WHEN_DIALING);
+ dumpSetting(s, p,
+ Settings.System.DTMF_TONE_TYPE_WHEN_DIALING,
+ SystemSettingsProto.DtmfTone.TYPE_PLAYED_WHEN_DIALING);
+ p.end(dtmfToneToken);
+
+ dumpSetting(s, p,
+ Settings.System.EGG_MODE,
+ SystemSettingsProto.EGG_MODE);
dumpSetting(s, p,
Settings.System.END_BUTTON_BEHAVIOR,
SystemSettingsProto.END_BUTTON_BEHAVIOR);
dumpSetting(s, p,
- Settings.System.ADVANCED_SETTINGS,
- SystemSettingsProto.ADVANCED_SETTINGS);
+ Settings.System.FONT_SCALE,
+ SystemSettingsProto.FONT_SCALE);
+
+ final long hapticFeedbackToken = p.start(SystemSettingsProto.HAPTIC_FEEDBACK);
+ dumpSetting(s, p,
+ Settings.System.HAPTIC_FEEDBACK_ENABLED,
+ SystemSettingsProto.HapticFeedback.ENABLED);
+ dumpSetting(s, p,
+ Settings.System.HAPTIC_FEEDBACK_INTENSITY,
+ SystemSettingsProto.HapticFeedback.INTENSITY);
+ p.end(hapticFeedbackToken);
+
+ dumpSetting(s, p,
+ Settings.System.HEARING_AID,
+ SystemSettingsProto.HEARING_AID);
+ dumpSetting(s, p,
+ Settings.System.LOCK_TO_APP_ENABLED,
+ SystemSettingsProto.LOCK_TO_APP_ENABLED);
+
+ final long lockscreenToken = p.start(SystemSettingsProto.LOCKSCREEN);
+ dumpSetting(s, p,
+ Settings.System.LOCKSCREEN_SOUNDS_ENABLED,
+ SystemSettingsProto.Lockscreen.SOUNDS_ENABLED);
+ dumpSetting(s, p,
+ Settings.System.LOCKSCREEN_DISABLED,
+ SystemSettingsProto.Lockscreen.DISABLED);
+ p.end(lockscreenToken);
+
+ dumpSetting(s, p,
+ Settings.System.MEDIA_BUTTON_RECEIVER,
+ SystemSettingsProto.MEDIA_BUTTON_RECEIVER);
+
+ final long notificationToken = p.start(SystemSettingsProto.NOTIFICATION);
+ dumpSetting(s, p,
+ Settings.System.NOTIFICATION_SOUND,
+ SystemSettingsProto.Notification.SOUND);
+ dumpSetting(s, p,
+ Settings.System.NOTIFICATION_SOUND_CACHE,
+ SystemSettingsProto.Notification.SOUND_CACHE);
+ dumpSetting(s, p,
+ Settings.System.NOTIFICATION_LIGHT_PULSE,
+ SystemSettingsProto.Notification.LIGHT_PULSE);
+ dumpSetting(s, p,
+ Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
+ SystemSettingsProto.Notification.VIBRATION_INTENSITY);
+ // Settings.System.NOTIFICATIONS_USE_RING_VOLUME intentionally excluded since it's deprecated.
+ p.end(notificationToken);
+
+ dumpSetting(s, p,
+ Settings.System.POINTER_SPEED,
+ SystemSettingsProto.POINTER_SPEED);
+
+ final long ringtoneToken = p.start(SystemSettingsProto.RINGTONE);
+ dumpSetting(s, p,
+ Settings.System.RINGTONE,
+ SystemSettingsProto.Ringtone.DEFAULT_URI);
+ dumpSetting(s, p,
+ Settings.System.RINGTONE_CACHE,
+ SystemSettingsProto.Ringtone.CACHE);
+ p.end(ringtoneToken);
+
+ final long rotationToken = p.start(SystemSettingsProto.ROTATION);
+ dumpSetting(s, p,
+ Settings.System.ACCELEROMETER_ROTATION,
+ SystemSettingsProto.Rotation.ACCELEROMETER_ROTATION);
+ dumpSetting(s, p,
+ Settings.System.USER_ROTATION,
+ SystemSettingsProto.Rotation.USER_ROTATION);
+ dumpSetting(s, p,
+ Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY,
+ SystemSettingsProto.Rotation.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY);
+ p.end(rotationToken);
+
+ dumpSetting(s, p,
+ Settings.System.RTT_CALLING_MODE,
+ SystemSettingsProto.RTT_CALLING_MODE);
+
+ final long screenToken = p.start(SystemSettingsProto.SCREEN);
+ dumpSetting(s, p,
+ Settings.System.SCREEN_OFF_TIMEOUT,
+ SystemSettingsProto.Screen.OFF_TIMEOUT);
+ dumpSetting(s, p,
+ Settings.System.SCREEN_BRIGHTNESS,
+ SystemSettingsProto.Screen.BRIGHTNESS);
+ dumpSetting(s, p,
+ Settings.System.SCREEN_BRIGHTNESS_FOR_VR,
+ SystemSettingsProto.Screen.BRIGHTNESS_FOR_VR);
+ dumpSetting(s, p,
+ Settings.System.SCREEN_BRIGHTNESS_MODE,
+ SystemSettingsProto.Screen.BRIGHTNESS_MODE);
+ dumpSetting(s, p,
+ Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
+ SystemSettingsProto.Screen.AUTO_BRIGHTNESS_ADJ);
+ p.end(screenToken);
+
+ dumpSetting(s, p,
+ Settings.System.SETUP_WIZARD_HAS_RUN,
+ SystemSettingsProto.SETUP_WIZARD_HAS_RUN);
+ dumpSetting(s, p,
+ Settings.System.SHOW_BATTERY_PERCENT,
+ SystemSettingsProto.SHOW_BATTERY_PERCENT);
+ dumpSetting(s, p,
+ Settings.System.SHOW_GTALK_SERVICE_STATUS,
+ SystemSettingsProto.SHOW_GTALK_SERVICE_STATUS);
+ // Settings.System.SHOW_PROCESSES intentionally excluded since it's deprecated.
+ // Settings.System.SHOW_WEB_SUGGESTIONS intentionally excluded since it's deprecated.
+
+ final long sipToken = p.start(SystemSettingsProto.SIP);
+ dumpSetting(s, p,
+ Settings.System.SIP_RECEIVE_CALLS,
+ SystemSettingsProto.Sip.RECEIVE_CALLS);
+ dumpSetting(s, p,
+ Settings.System.SIP_CALL_OPTIONS,
+ SystemSettingsProto.Sip.CALL_OPTIONS);
+ dumpSetting(s, p,
+ Settings.System.SIP_ALWAYS,
+ SystemSettingsProto.Sip.ALWAYS);
+ dumpSetting(s, p,
+ Settings.System.SIP_ADDRESS_ONLY,
+ SystemSettingsProto.Sip.ADDRESS_ONLY);
+ // Settings.System.SIP_ASK_ME_EACH_TIME intentionally excluded since it's deprecated.
+ p.end(sipToken);
+
+ dumpSetting(s, p,
+ Settings.System.SOUND_EFFECTS_ENABLED,
+ SystemSettingsProto.SOUND_EFFECTS_ENABLED);
+ // Settings.System.POWER_SOUNDS_ENABLED intentionally excluded since it's deprecated.
+ // Settings.System.DOCK_SOUNDS_ENABLED intentionally excluded since it's deprecated.
+ // Settings.System.LOW_BATTERY_SOUND intentionally excluded since it's deprecated.
+ // Settings.System.DESK_DOCK_SOUND intentionally excluded since it's deprecated.
+ // Settings.System.DESK_UNDOCK_SOUND intentionally excluded since it's deprecated.
+ // Settings.System.CAR_DOCK_SOUND intentionally excluded since it's deprecated.
+ // Settings.System.CAR_UNDOCK_SOUND intentionally excluded since it's deprecated.
+ // Settings.System.LOCK_SOUND intentionally excluded since it's deprecated.
+ // Settings.System.UNLOCK_SOUND intentionally excluded since it's deprecated.
+ dumpSetting(s, p,
+ Settings.System.SYSTEM_LOCALES,
+ SystemSettingsProto.SYSTEM_LOCALES);
+
+ final long textToken = p.start(SystemSettingsProto.TEXT);
+ dumpSetting(s, p,
+ Settings.System.TEXT_AUTO_REPLACE,
+ SystemSettingsProto.Text.AUTO_REPLACE);
+ dumpSetting(s, p,
+ Settings.System.TEXT_AUTO_CAPS,
+ SystemSettingsProto.Text.AUTO_CAPS);
+ dumpSetting(s, p,
+ Settings.System.TEXT_AUTO_PUNCTUATE,
+ SystemSettingsProto.Text.AUTO_PUNCTUATE);
+ dumpSetting(s, p,
+ Settings.System.TEXT_SHOW_PASSWORD,
+ SystemSettingsProto.Text.SHOW_PASSWORD);
+ p.end(textToken);
+
+ // Settings.System.AUTO_TIME intentionally excluded since it's deprecated.
+ // Settings.System.AUTO_TIME_ZONE intentionally excluded since it's deprecated.
+ dumpSetting(s, p,
+ Settings.System.TIME_12_24,
+ SystemSettingsProto.TIME_12_24);
+ dumpSetting(s, p,
+ Settings.System.TTY_MODE,
+ SystemSettingsProto.TTY_MODE);
+
+ final long vibrateToken = p.start(SystemSettingsProto.VIBRATE);
+ dumpSetting(s, p,
+ Settings.System.VIBRATE_ON,
+ SystemSettingsProto.Vibrate.ON);
+ dumpSetting(s, p,
+ Settings.System.VIBRATE_INPUT_DEVICES,
+ SystemSettingsProto.Vibrate.INPUT_DEVICES);
+ dumpSetting(s, p,
+ Settings.System.VIBRATE_IN_SILENT,
+ SystemSettingsProto.Vibrate.IN_SILENT);
+ dumpSetting(s, p,
+ Settings.System.VIBRATE_WHEN_RINGING,
+ SystemSettingsProto.Vibrate.WHEN_RINGING);
+ p.end(vibrateToken);
+
+ final long volumeToken = p.start(SystemSettingsProto.VOLUME);
+ dumpSetting(s, p,
+ Settings.System.VOLUME_RING,
+ SystemSettingsProto.Volume.RING);
+ dumpSetting(s, p,
+ Settings.System.VOLUME_SYSTEM,
+ SystemSettingsProto.Volume.SYSTEM);
+ dumpSetting(s, p,
+ Settings.System.VOLUME_VOICE,
+ SystemSettingsProto.Volume.VOICE);
+ dumpSetting(s, p,
+ Settings.System.VOLUME_MUSIC,
+ SystemSettingsProto.Volume.MUSIC);
+ dumpSetting(s, p,
+ Settings.System.VOLUME_ALARM,
+ SystemSettingsProto.Volume.ALARM);
+ dumpSetting(s, p,
+ Settings.System.VOLUME_NOTIFICATION,
+ SystemSettingsProto.Volume.NOTIFICATION);
+ dumpSetting(s, p,
+ Settings.System.VOLUME_BLUETOOTH_SCO,
+ SystemSettingsProto.Volume.BLUETOOTH_SCO);
+ dumpSetting(s, p,
+ Settings.System.VOLUME_ACCESSIBILITY,
+ SystemSettingsProto.Volume.ACCESSIBILITY);
+ dumpSetting(s, p,
+ Settings.System.VOLUME_MASTER,
+ SystemSettingsProto.Volume.MASTER);
+ dumpSetting(s, p,
+ Settings.System.MASTER_MONO,
+ SystemSettingsProto.Volume.MASTER_MONO);
+ dumpSetting(s, p,
+ Settings.System.MODE_RINGER_STREAMS_AFFECTED,
+ SystemSettingsProto.Volume.MODE_RINGER_STREAMS_AFFECTED);
+ dumpSetting(s, p,
+ Settings.System.MUTE_STREAMS_AFFECTED,
+ SystemSettingsProto.Volume.MUTE_STREAMS_AFFECTED);
+ p.end(volumeToken);
+
+ dumpSetting(s, p,
+ Settings.System.WHEN_TO_MAKE_WIFI_CALLS,
+ SystemSettingsProto.WHEN_TO_MAKE_WIFI_CALLS);
+
+ // Please insert new settings using the same order as in SecureSettingsProto.
+
+ // The rest of the settings were moved to Settings.Secure, and are thus excluded here since
+ // they're deprecated from Settings.System.
+
+ // Settings.System.STAY_ON_WHILE_PLUGGED_IN intentionally excluded since it's deprecated.
// Settings.System.AIRPLANE_MODE_ON intentionally excluded since it's deprecated.
// Settings.System.RADIO_BLUETOOTH intentionally excluded since it's just a constant.
// Settings.System.RADIO_WIFI intentionally excluded since it's just a constant.
@@ -2184,245 +2569,24 @@
// Settings.System.WIFI_STATIC_NETMASK intentionally excluded since it's deprecated.
// Settings.System.WIFI_STATIC_DNS1 intentionally excluded since it's deprecated.
// Settings.System.WIFI_STATIC_DNS2 intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.System.BLUETOOTH_DISCOVERABILITY,
- SystemSettingsProto.BLUETOOTH_DISCOVERABILITY);
- dumpSetting(s, p,
- Settings.System.BLUETOOTH_DISCOVERABILITY_TIMEOUT,
- SystemSettingsProto.BLUETOOTH_DISCOVERABILITY_TIMEOUT);
// Settings.System.LOCK_PATTERN_ENABLED intentionally excluded since it's deprecated.
// Settings.System.LOCK_PATTERN_VISIBLE intentionally excluded since it's deprecated.
// Settings.System.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED intentionally excluded since it's deprecated.
- // Settings.System.NEXT_ALARM_FORMATTED intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.System.FONT_SCALE,
- SystemSettingsProto.FONT_SCALE);
- dumpSetting(s, p,
- Settings.System.SYSTEM_LOCALES,
- SystemSettingsProto.SYSTEM_LOCALES);
// Settings.System.DEBUG_APP intentionally excluded since it's deprecated.
// Settings.System.WAIT_FOR_DEBUGGER intentionally excluded since it's deprecated.
// Settings.System.DIM_SCREEN intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.System.DISPLAY_COLOR_MODE,
- SystemSettingsProto.DISPLAY_COLOR_MODE);
- dumpSetting(s, p,
- Settings.System.SCREEN_OFF_TIMEOUT,
- SystemSettingsProto.SCREEN_OFF_TIMEOUT);
- dumpSetting(s, p,
- Settings.System.SCREEN_BRIGHTNESS,
- SystemSettingsProto.SCREEN_BRIGHTNESS);
- dumpSetting(s, p,
- Settings.System.SCREEN_BRIGHTNESS_FOR_VR,
- SystemSettingsProto.SCREEN_BRIGHTNESS_FOR_VR);
- dumpSetting(s, p,
- Settings.System.SCREEN_BRIGHTNESS_MODE,
- SystemSettingsProto.SCREEN_BRIGHTNESS_MODE);
- dumpSetting(s, p,
- Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
- SystemSettingsProto.SCREEN_AUTO_BRIGHTNESS_ADJ);
- // Settings.System.SHOW_PROCESSES intentionally excluded since it's deprecated.
// Settings.System.ALWAYS_FINISH_ACTIVITIES intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.System.MODE_RINGER_STREAMS_AFFECTED,
- SystemSettingsProto.MODE_RINGER_STREAMS_AFFECTED);
- dumpSetting(s, p,
- Settings.System.MUTE_STREAMS_AFFECTED,
- SystemSettingsProto.MUTE_STREAMS_AFFECTED);
- dumpSetting(s, p,
- Settings.System.VIBRATE_ON,
- SystemSettingsProto.VIBRATE_ON);
- dumpSetting(s, p,
- Settings.System.VIBRATE_INPUT_DEVICES,
- SystemSettingsProto.VIBRATE_INPUT_DEVICES);
- dumpSetting(s, p,
- Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- SystemSettingsProto.NOTIFICATION_VIBRATION_INTENSITY);
- dumpSetting(s, p,
- Settings.System.HAPTIC_FEEDBACK_INTENSITY,
- SystemSettingsProto.HAPTIC_FEEDBACK_INTENSITY);
- dumpSetting(s, p,
- Settings.System.VOLUME_RING,
- SystemSettingsProto.VOLUME_RING);
- dumpSetting(s, p,
- Settings.System.VOLUME_SYSTEM,
- SystemSettingsProto.VOLUME_SYSTEM);
- dumpSetting(s, p,
- Settings.System.VOLUME_VOICE,
- SystemSettingsProto.VOLUME_VOICE);
- dumpSetting(s, p,
- Settings.System.VOLUME_MUSIC,
- SystemSettingsProto.VOLUME_MUSIC);
- dumpSetting(s, p,
- Settings.System.VOLUME_ALARM,
- SystemSettingsProto.VOLUME_ALARM);
- dumpSetting(s, p,
- Settings.System.VOLUME_NOTIFICATION,
- SystemSettingsProto.VOLUME_NOTIFICATION);
- dumpSetting(s, p,
- Settings.System.VOLUME_BLUETOOTH_SCO,
- SystemSettingsProto.VOLUME_BLUETOOTH_SCO);
- dumpSetting(s, p,
- Settings.System.VOLUME_ACCESSIBILITY,
- SystemSettingsProto.VOLUME_ACCESSIBILITY);
- dumpSetting(s, p,
- Settings.System.VOLUME_MASTER,
- SystemSettingsProto.VOLUME_MASTER);
- dumpSetting(s, p,
- Settings.System.MASTER_MONO,
- SystemSettingsProto.MASTER_MONO);
- // Settings.System.NOTIFICATIONS_USE_RING_VOLUME intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.System.VIBRATE_IN_SILENT,
- SystemSettingsProto.VIBRATE_IN_SILENT);
- dumpSetting(s, p,
- Settings.System.APPEND_FOR_LAST_AUDIBLE,
- SystemSettingsProto.APPEND_FOR_LAST_AUDIBLE);
- dumpSetting(s, p,
- Settings.System.RINGTONE,
- SystemSettingsProto.RINGTONE);
- dumpSetting(s, p,
- Settings.System.RINGTONE_CACHE,
- SystemSettingsProto.RINGTONE_CACHE);
- dumpSetting(s, p,
- Settings.System.NOTIFICATION_SOUND,
- SystemSettingsProto.NOTIFICATION_SOUND);
- dumpSetting(s, p,
- Settings.System.NOTIFICATION_SOUND_CACHE,
- SystemSettingsProto.NOTIFICATION_SOUND_CACHE);
- dumpSetting(s, p,
- Settings.System.ALARM_ALERT,
- SystemSettingsProto.ALARM_ALERT);
- dumpSetting(s, p,
- Settings.System.ALARM_ALERT_CACHE,
- SystemSettingsProto.ALARM_ALERT_CACHE);
- dumpSetting(s, p,
- Settings.System.MEDIA_BUTTON_RECEIVER,
- SystemSettingsProto.MEDIA_BUTTON_RECEIVER);
- dumpSetting(s, p,
- Settings.System.TEXT_AUTO_REPLACE,
- SystemSettingsProto.TEXT_AUTO_REPLACE);
- dumpSetting(s, p,
- Settings.System.TEXT_AUTO_CAPS,
- SystemSettingsProto.TEXT_AUTO_CAPS);
- dumpSetting(s, p,
- Settings.System.TEXT_AUTO_PUNCTUATE,
- SystemSettingsProto.TEXT_AUTO_PUNCTUATE);
- dumpSetting(s, p,
- Settings.System.TEXT_SHOW_PASSWORD,
- SystemSettingsProto.TEXT_SHOW_PASSWORD);
- dumpSetting(s, p,
- Settings.System.SHOW_GTALK_SERVICE_STATUS,
- SystemSettingsProto.SHOW_GTALK_SERVICE_STATUS);
+ // Settings.System.APPEND_FOR_LAST_AUDIBLE intentionally excluded since it hasn't been used since API 2.
// Settings.System.WALLPAPER_ACTIVITY intentionally excluded since it's deprecated.
- // Settings.System.AUTO_TIME intentionally excluded since it's deprecated.
- // Settings.System.AUTO_TIME_ZONE intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.System.TIME_12_24,
- SystemSettingsProto.TIME_12_24);
- dumpSetting(s, p,
- Settings.System.DATE_FORMAT,
- SystemSettingsProto.DATE_FORMAT);
- dumpSetting(s, p,
- Settings.System.SETUP_WIZARD_HAS_RUN,
- SystemSettingsProto.SETUP_WIZARD_HAS_RUN);
// Settings.System.WINDOW_ANIMATION_SCALE intentionally excluded since it's deprecated.
// Settings.System.TRANSITION_ANIMATION_SCALE intentionally excluded since it's deprecated.
// Settings.System.ANIMATOR_ANIMATION_SCALE intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.System.ACCELEROMETER_ROTATION,
- SystemSettingsProto.ACCELEROMETER_ROTATION);
- dumpSetting(s, p,
- Settings.System.USER_ROTATION,
- SystemSettingsProto.USER_ROTATION);
- dumpSetting(s, p,
- Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY,
- SystemSettingsProto.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY);
- dumpSetting(s, p,
- Settings.System.VIBRATE_WHEN_RINGING,
- SystemSettingsProto.VIBRATE_WHEN_RINGING);
- dumpSetting(s, p,
- Settings.System.DTMF_TONE_WHEN_DIALING,
- SystemSettingsProto.DTMF_TONE_WHEN_DIALING);
- dumpSetting(s, p,
- Settings.System.DTMF_TONE_TYPE_WHEN_DIALING,
- SystemSettingsProto.DTMF_TONE_TYPE_WHEN_DIALING);
- dumpSetting(s, p,
- Settings.System.HEARING_AID,
- SystemSettingsProto.HEARING_AID);
- dumpSetting(s, p,
- Settings.System.TTY_MODE,
- SystemSettingsProto.TTY_MODE);
- dumpSetting(s, p,
- Settings.System.RTT_CALLING_MODE,
- SystemSettingsProto.RTT_CALLING_MODE);
- dumpSetting(s, p,
- Settings.System.SOUND_EFFECTS_ENABLED,
- SystemSettingsProto.SOUND_EFFECTS_ENABLED);
- dumpSetting(s, p,
- Settings.System.HAPTIC_FEEDBACK_ENABLED,
- SystemSettingsProto.HAPTIC_FEEDBACK_ENABLED);
- // Settings.System.SHOW_WEB_SUGGESTIONS intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.System.NOTIFICATION_LIGHT_PULSE,
- SystemSettingsProto.NOTIFICATION_LIGHT_PULSE);
- dumpSetting(s, p,
- Settings.System.POINTER_LOCATION,
- SystemSettingsProto.POINTER_LOCATION);
- dumpSetting(s, p,
- Settings.System.SHOW_TOUCHES,
- SystemSettingsProto.SHOW_TOUCHES);
- dumpSetting(s, p,
- Settings.System.WINDOW_ORIENTATION_LISTENER_LOG,
- SystemSettingsProto.WINDOW_ORIENTATION_LISTENER_LOG);
- // Settings.System.POWER_SOUNDS_ENABLED intentionally excluded since it's deprecated.
- // Settings.System.DOCK_SOUNDS_ENABLED intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.System.LOCKSCREEN_SOUNDS_ENABLED,
- SystemSettingsProto.LOCKSCREEN_SOUNDS_ENABLED);
- dumpSetting(s, p,
- Settings.System.LOCKSCREEN_DISABLED,
- SystemSettingsProto.LOCKSCREEN_DISABLED);
- // Settings.System.LOW_BATTERY_SOUND intentionally excluded since it's deprecated.
- // Settings.System.DESK_DOCK_SOUND intentionally excluded since it's deprecated.
- // Settings.System.DESK_UNDOCK_SOUND intentionally excluded since it's deprecated.
- // Settings.System.CAR_DOCK_SOUND intentionally excluded since it's deprecated.
- // Settings.System.CAR_UNDOCK_SOUND intentionally excluded since it's deprecated.
- // Settings.System.LOCK_SOUND intentionally excluded since it's deprecated.
- // Settings.System.UNLOCK_SOUND intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.System.SIP_RECEIVE_CALLS,
- SystemSettingsProto.SIP_RECEIVE_CALLS);
- dumpSetting(s, p,
- Settings.System.SIP_CALL_OPTIONS,
- SystemSettingsProto.SIP_CALL_OPTIONS);
- dumpSetting(s, p,
- Settings.System.SIP_ALWAYS,
- SystemSettingsProto.SIP_ALWAYS);
- dumpSetting(s, p,
- Settings.System.SIP_ADDRESS_ONLY,
- SystemSettingsProto.SIP_ADDRESS_ONLY);
- // Settings.System.SIP_ASK_ME_EACH_TIME intentionally excluded since it's deprecated.
- dumpSetting(s, p,
- Settings.System.POINTER_SPEED,
- SystemSettingsProto.POINTER_SPEED);
- dumpSetting(s, p,
- Settings.System.LOCK_TO_APP_ENABLED,
- SystemSettingsProto.LOCK_TO_APP_ENABLED);
- dumpSetting(s, p,
- Settings.System.EGG_MODE,
- SystemSettingsProto.EGG_MODE);
- dumpSetting(s, p,
- Settings.System.SHOW_BATTERY_PERCENT,
- SystemSettingsProto.SHOW_BATTERY_PERCENT);
- dumpSetting(s, p,
- Settings.System.WHEN_TO_MAKE_WIFI_CALLS,
- SystemSettingsProto.WHEN_TO_MAKE_WIFI_CALLS);
+
// The rest of the settings were moved to Settings.Secure, and are thus excluded here since
// they're deprecated from Settings.System.
- // Please insert new settings using the same order as in Settings.System.
-
+ // Please insert new settings using the same order as in SecureSettingsProto.
p.end(token);
+ // Please insert new settings using the same order as in SecureSettingsProto.
}
}
diff --git a/packages/SystemUI/res/layout/car_volume_dialog.xml b/packages/SystemUI/res/layout/car_volume_dialog.xml
index dca50a5..e45c0f9 100644
--- a/packages/SystemUI/res/layout/car_volume_dialog.xml
+++ b/packages/SystemUI/res/layout/car_volume_dialog.xml
@@ -24,7 +24,7 @@
android:clipChildren="false" >
<LinearLayout
android:id="@+id/volume_dialog"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
android:orientation="vertical"
@@ -53,14 +53,15 @@
android:layout_width="wrap_content"
android:layout_height="@dimen/car_single_line_list_item_height"
android:gravity="center"
- android:layout_marginEnd="@dimen/car_keyline_1">
- <ImageButton
+ android:layout_marginEnd="@dimen/car_keyline_1"
+ android:layout_gravity="end">
+ <com.android.keyguard.AlphaOptimizedImageButton
android:id="@+id/expand"
android:layout_gravity="center"
android:layout_width="@dimen/car_primary_icon_size"
android:layout_height="@dimen/car_primary_icon_size"
- android:layout_marginEnd="@dimen/car_keyline_1"
android:src="@drawable/car_ic_arrow_drop_up"
+ android:background="?android:attr/selectableItemBackground"
android:tint="@color/car_tint"
android:scaleType="fitCenter"
/>
diff --git a/packages/SystemUI/res/layout/car_volume_dialog_row.xml b/packages/SystemUI/res/layout/car_volume_dialog_row.xml
index 14baf49..33cecfa 100644
--- a/packages/SystemUI/res/layout/car_volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/car_volume_dialog_row.xml
@@ -33,13 +33,14 @@
android:layout_width="@dimen/car_primary_icon_size"
android:layout_height="@dimen/car_primary_icon_size"
android:layout_marginStart="@dimen/car_keyline_1"
+ android:background="?android:attr/selectableItemBackground"
android:tint="@color/car_tint"
android:scaleType="fitCenter"
android:soundEffectsEnabled="false" />
<SeekBar
android:id="@+id/volume_row_slider"
android:clickable="true"
- android:layout_marginStart="@dimen/car_keyline_3"
+ android:layout_marginStart="@dimen/car_keyline_1_keyline_3_diff"
android:layout_marginEnd="@dimen/car_keyline_3"
android:layout_width="match_parent"
android:layout_height="@dimen/car_single_line_list_item_height"/>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
index f38129f..388b633 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
@@ -31,25 +31,23 @@
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"
- android:textAppearance="@style/TextAppearance.StatusBar.Clock"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:singleLine="true"
+ android:gravity="center_vertical|start"
android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
- android:gravity="center_vertical|start"
- systemui:showDark="false"
- />
+ android:singleLine="true"
+ android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+ systemui:showDark="false" />
<com.android.systemui.statusbar.policy.DateView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:padding="4dp"
+ android:gravity="center_vertical"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
android:textSize="@dimen/qs_time_collapsed_size"
- android:gravity="center_vertical"
systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
<android.widget.Space
@@ -57,12 +55,11 @@
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
- android:gravity="center_vertical|center_horizontal"
- />
+ android:gravity="center_vertical|center_horizontal" />
- <com.android.systemui.BatteryMeterView android:id="@+id/battery"
+ <com.android.systemui.BatteryMeterView
+ android:id="@+id/battery"
android:layout_height="match_parent"
android:layout_width="wrap_content"
- android:gravity="center_vertical|end"
- />
+ android:gravity="center_vertical|end" />
</LinearLayout>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index f76603b..711d550 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -45,9 +45,6 @@
interface. This name is in the ComponentName flattened format (package/class) -->
<string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.StatusBar</string>
- <!-- Component name of launcher service for overview to connect to -->
- <string name="config_overviewServiceComponent" translatable="false">com.android.launcher3/com.android.quickstep.TouchInteractionService</string>
-
<!-- Whether or not we show the number in the bar. -->
<bool name="config_statusBarShowNumber">false</bool>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 909c18b..8c00af6 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2096,6 +2096,8 @@
<string name="notification_channel_general">General Messages</string>
<!-- Title for the notification channel for problems with storage (i.e. low disk). [CHAR LIMIT=NONE] -->
<string name="notification_channel_storage">Storage</string>
+ <!-- Title for the notification channel for hints and suggestions. [CHAR LIMIT=NONE] -->
+ <string name="notification_channel_hints">Hints</string>
<!-- App label of the instant apps notification [CHAR LIMIT=60] -->
<string name="instant_apps">Instant Apps</string>
@@ -2186,4 +2188,25 @@
<string-array name="recents_onboarding_blacklisted_packages" translatable="false">
</string-array>
+ <!-- The title of the notification to suggest enabling automatic battery saver. [CHAR LIMIT=NONE]-->
+ <string name="auto_saver_title">Tap to schedule Battery Saver</string>
+
+ <!-- The content of the notification to suggest enabling automatic battery saver. [CHAR LIMIT=NONE]-->
+ <string name="auto_saver_text">Turn on automatically when battery is at <xliff:g id="percentage">%d</xliff:g>%%</string>
+
+ <!-- An action on the notification to suggest enabling automatic battery saver: Do not turn on automatic battery saver. [CHAR LIMIT=NONE]-->
+ <string name="no_auto_saver_action">No thanks</string>
+
+ <!-- The title of the dialog that tells that scheduled (i.e. automatic) battery saver has been turned on. [CHAR LIMIT=NONE]-->
+ <string name="auto_saver_enabled_title">Battery Saver schedule turned on</string>
+
+ <!-- The content of the dialog that tells that scheduled (i.e. automatic) battery saver has been turned on. [CHAR LIMIT=NONE]-->
+ <string name="auto_saver_enabled_text">Battery Saver will turn on automatically once battery goes below <xliff:g id="percentage">%d</xliff:g>%%.</string>
+
+ <!-- An action on the dialog that tells that scheduled (i.e. automatic) battery saver: open the battery saver setting. [CHAR LIMIT=NONE]-->
+ <string name="open_saver_setting_action">Settings</string>
+
+ <!-- An action on the dialog that tells that scheduled (i.e. automatic) battery saver: user acknowledges and closes the dialog. [CHAR LIMIT=NONE]-->
+ <string name="auto_saver_okay_action">Got it</string>
+
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java
index 14767f1..20d1418 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java
@@ -19,6 +19,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
@@ -106,11 +107,12 @@
return createDrawableFromBitmap(tdIcon, userId, desc);
}
if (desc.getIconResource() != 0) {
- // TODO: Use task context here
try {
- return createBadgedDrawable(
- mContext.getDrawable(desc.getIconResource()), userId, desc);
- } catch (Resources.NotFoundException e) {
+ Context packageContext = mContext.createPackageContextAsUser(
+ taskKey.getPackageName(), 0, UserHandle.of(userId));
+ return createBadgedDrawable(packageContext.getDrawable(desc.getIconResource()),
+ userId, desc);
+ } catch (Resources.NotFoundException|PackageManager.NameNotFoundException e) {
Log.e(TAG, "Could not find icon drawable from resource", e);
}
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
index 6bddbe0..6af89fc 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
@@ -80,6 +80,13 @@
return this.baseIntent.getComponent();
}
+ public String getPackageName() {
+ if (this.baseIntent.getComponent() != null) {
+ return this.baseIntent.getComponent().getPackageName();
+ }
+ return this.baseIntent.getPackage();
+ }
+
@Override
public boolean equals(Object o) {
if (!(o instanceof TaskKey)) {
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 1ae06d7..0683514 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -81,6 +81,14 @@
private float mDarkIntensity;
private int mUser;
+ /**
+ * Whether we should use colors that adapt based on wallpaper/the scrim behind quick settings.
+ */
+ private boolean mUseWallpaperTextColors;
+
+ private int mNonAdaptedForegroundColor;
+ private int mNonAdaptedBackgroundColor;
+
public BatteryMeterView(Context context) {
this(context, null, 0);
}
@@ -140,6 +148,29 @@
updateShowPercent();
}
+ /**
+ * Sets whether the battery meter view uses the wallpaperTextColor. If we're not using it, we'll
+ * revert back to dark-mode-based/tinted colors.
+ *
+ * @param shouldUseWallpaperTextColor whether we should use wallpaperTextColor for all
+ * components
+ */
+ public void useWallpaperTextColor(boolean shouldUseWallpaperTextColor) {
+ if (shouldUseWallpaperTextColor == mUseWallpaperTextColors) {
+ return;
+ }
+
+ mUseWallpaperTextColors = shouldUseWallpaperTextColor;
+
+ if (mUseWallpaperTextColors) {
+ updateColors(
+ Utils.getColorAttr(mContext, R.attr.wallpaperTextColor),
+ Utils.getColorAttr(mContext, R.attr.wallpaperTextColorSecondary));
+ } else {
+ updateColors(mNonAdaptedForegroundColor, mNonAdaptedBackgroundColor);
+ }
+ }
+
public void setColorsFromContext(Context context) {
if (context == null) {
return;
@@ -179,7 +210,8 @@
getContext().getContentResolver().registerContentObserver(
Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mSettingObserver, mUser);
updateShowPercent();
- Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
+ Dependency.get(TunerService.class)
+ .addTunable(this, StatusBarIconController.ICON_BLACKLIST);
Dependency.get(ConfigurationController.class).addCallback(this);
mUserTracker.startTracking();
}
@@ -273,19 +305,23 @@
@Override
public void onDarkChanged(Rect area, float darkIntensity, int tint) {
mDarkIntensity = darkIntensity;
+
float intensity = DarkIconDispatcher.isInArea(area, this) ? darkIntensity : 0;
- int foreground = getColorForDarkIntensity(intensity, mLightModeFillColor,
- mDarkModeFillColor);
- int background = getColorForDarkIntensity(intensity, mLightModeBackgroundColor,
- mDarkModeBackgroundColor);
- mDrawable.setColors(foreground, background);
- setTextColor(foreground);
+ mNonAdaptedForegroundColor = getColorForDarkIntensity(
+ intensity, mLightModeFillColor, mDarkModeFillColor);
+ mNonAdaptedBackgroundColor = getColorForDarkIntensity(
+ intensity, mLightModeBackgroundColor,mDarkModeBackgroundColor);
+
+ if (!mUseWallpaperTextColors) {
+ updateColors(mNonAdaptedForegroundColor, mNonAdaptedBackgroundColor);
+ }
}
- public void setTextColor(int color) {
- mTextColor = color;
+ private void updateColors(int foregroundColor, int backgroundColor) {
+ mDrawable.setColors(foregroundColor, backgroundColor);
+ mTextColor = foregroundColor;
if (mBatteryPercentView != null) {
- mBatteryPercentView.setTextColor(color);
+ mBatteryPercentView.setTextColor(foregroundColor);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index a59c97e..a4f8d8c 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -24,11 +24,13 @@
import android.graphics.RectF;
import android.graphics.Region.Op;
import android.os.AsyncTask;
+import android.os.Handler;
import android.os.Trace;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.Display;
import android.view.DisplayInfo;
+import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.WindowManager;
@@ -45,6 +47,7 @@
private static final String GL_LOG_TAG = "ImageWallpaperGL";
private static final boolean DEBUG = false;
private static final String PROPERTY_KERNEL_QEMU = "ro.kernel.qemu";
+ private static final long DELAY_FORGET_WALLPAPER = 5000;
private WallpaperManager mWallpaperManager;
private DrawableEngine mEngine;
@@ -69,6 +72,10 @@
}
class DrawableEngine extends Engine {
+ private final Runnable mUnloadWallpaperCallback = () -> {
+ unloadWallpaper(false /* forgetSize */);
+ };
+
Bitmap mBackground;
int mBackgroundWidth = -1, mBackgroundHeight = -1;
int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
@@ -331,6 +338,7 @@
}
drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
+ scheduleUnloadWallpaper();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
@@ -433,6 +441,9 @@
mBackgroundHeight = -1;
}
+ final Surface surface = getSurfaceHolder().getSurface();
+ surface.hwuiDestroy();
+
mLoader = new AsyncTask<Void, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(Void... params) {
@@ -442,6 +453,12 @@
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
+ private void scheduleUnloadWallpaper() {
+ Handler handler = getMainThreadHandler();
+ handler.removeCallbacks(mUnloadWallpaperCallback);
+ handler.postDelayed(mUnloadWallpaperCallback, DELAY_FORGET_WALLPAPER);
+ }
+
@Override
protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
super.dump(prefix, fd, out, args);
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index a4af6b2..2983df6 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -57,6 +57,8 @@
*/
public class OverviewProxyService implements CallbackController<OverviewProxyListener>, Dumpable {
+ private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
+
public static final String TAG_OPS = "OverviewProxyService";
public static final boolean DEBUG_OVERVIEW_PROXY = false;
private static final long BACKOFF_MILLIS = 5000;
@@ -64,7 +66,7 @@
private final Context mContext;
private final Handler mHandler;
private final Runnable mConnectionRunnable = this::internalConnectToCurrentUser;
- private final ComponentName mLauncherComponentName;
+ private final ComponentName mRecentsComponentName;
private final DeviceProvisionedController mDeviceProvisionedController
= Dependency.get(DeviceProvisionedController.class);
private final List<OverviewProxyListener> mConnectionCallbacks = new ArrayList<>();
@@ -191,8 +193,8 @@
mContext = context;
mHandler = new Handler();
mConnectionBackoffAttempts = 0;
- mLauncherComponentName = ComponentName
- .unflattenFromString(context.getString(R.string.config_overviewServiceComponent));
+ mRecentsComponentName = ComponentName.unflattenFromString(context.getString(
+ com.android.internal.R.string.config_recentsComponentName));
// Listen for the package update changes.
if (SystemServicesProxy.getInstance(context)
@@ -200,7 +202,7 @@
mDeviceProvisionedController.addCallback(mDeviceProvisionedCallback);
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addDataScheme("package");
- filter.addDataSchemeSpecificPart(mLauncherComponentName.getPackageName(),
+ filter.addDataSchemeSpecificPart(mRecentsComponentName.getPackageName(),
PatternMatcher.PATTERN_LITERAL);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
mContext.registerReceiver(mLauncherAddedReceiver, filter);
@@ -223,8 +225,8 @@
return;
}
mHandler.removeCallbacks(mConnectionRunnable);
- Intent launcherServiceIntent = new Intent();
- launcherServiceIntent.setComponent(mLauncherComponentName);
+ Intent launcherServiceIntent = new Intent(ACTION_QUICKSTEP)
+ .setPackage(mRecentsComponentName.getPackageName());
boolean bound = mContext.bindServiceAsUser(launcherServiceIntent,
mOverviewServiceConnection, Context.BIND_AUTO_CREATE,
UserHandle.of(mDeviceProvisionedController.getCurrentUser()));
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 391843c..039e7b5 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -31,6 +31,7 @@
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.NotificationBlockingHelperManager;
import com.android.systemui.statusbar.NotificationEntryManager;
import com.android.systemui.statusbar.NotificationGutsManager;
import com.android.systemui.statusbar.NotificationListener;
@@ -130,6 +131,8 @@
providers.put(NotificationGroupManager.class, NotificationGroupManager::new);
providers.put(NotificationMediaManager.class, () -> new NotificationMediaManager(context));
providers.put(NotificationGutsManager.class, () -> new NotificationGutsManager(context));
+ providers.put(NotificationBlockingHelperManager.class,
+ () -> new NotificationBlockingHelperManager(context));
providers.put(NotificationRemoteInputManager.class,
() -> new NotificationRemoteInputManager(context));
providers.put(SmartReplyConstants.class,
diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
index 4b15fbc..3577c0f 100644
--- a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
@@ -18,8 +18,8 @@
import android.content.Context;
import android.content.pm.PackageManager;
-import android.hardware.fingerprint.FingerprintDialog;
-import android.hardware.fingerprint.IFingerprintDialogReceiver;
+import android.hardware.biometrics.BiometricDialog;
+import android.hardware.biometrics.IBiometricDialogReceiver;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -48,7 +48,7 @@
private FingerprintDialogView mDialogView;
private WindowManager mWindowManager;
- private IFingerprintDialogReceiver mReceiver;
+ private IBiometricDialogReceiver mReceiver;
private boolean mDialogShowing;
private Handler mHandler = new Handler() {
@@ -97,7 +97,7 @@
}
@Override
- public void showFingerprintDialog(Bundle bundle, IFingerprintDialogReceiver receiver) {
+ public void showFingerprintDialog(Bundle bundle, IBiometricDialogReceiver receiver) {
if (DEBUG) Log.d(TAG, "showFingerprintDialog");
// Remove these messages as they are part of the previous client
mHandler.removeMessages(MSG_FINGERPRINT_ERROR);
@@ -139,7 +139,7 @@
Log.w(TAG, "Dialog already showing");
return;
}
- mReceiver = (IFingerprintDialogReceiver) args.arg2;
+ mReceiver = (IBiometricDialogReceiver) args.arg2;
mDialogView.setBundle((Bundle)args.arg1);
mWindowManager.addView(mDialogView, mDialogView.getLayoutParams());
mDialogShowing = true;
@@ -147,6 +147,9 @@
private void handleFingerprintAuthenticated() {
if (DEBUG) Log.d(TAG, "handleFingerprintAuthenticated");
+ mDialogView.announceForAccessibility(
+ mContext.getResources().getText(
+ com.android.internal.R.string.fingerprint_authenticated));
handleHideDialog(false /* userCanceled */);
}
@@ -174,7 +177,7 @@
}
if (userCanceled) {
try {
- mReceiver.onDialogDismissed(FingerprintDialog.DISMISSED_REASON_USER_CANCEL);
+ mReceiver.onDialogDismissed(BiometricDialog.DISMISSED_REASON_USER_CANCEL);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException when hiding dialog", e);
}
@@ -190,7 +193,7 @@
return;
}
try {
- mReceiver.onDialogDismissed(FingerprintDialog.DISMISSED_REASON_NEGATIVE);
+ mReceiver.onDialogDismissed(BiometricDialog.DISMISSED_REASON_NEGATIVE);
} catch (RemoteException e) {
Log.e(TAG, "Remote exception when handling negative button", e);
}
@@ -203,7 +206,7 @@
return;
}
try {
- mReceiver.onDialogDismissed(FingerprintDialog.DISMISSED_REASON_POSITIVE);
+ mReceiver.onDialogDismissed(BiometricDialog.DISMISSED_REASON_POSITIVE);
} catch (RemoteException e) {
Log.e(TAG, "Remote exception when handling positive button", e);
}
diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
index ebdc703..95258b0 100644
--- a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
@@ -23,7 +23,7 @@
import android.graphics.PorterDuff;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
-import android.hardware.fingerprint.FingerprintDialog;
+import android.hardware.biometrics.BiometricDialog;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -55,7 +55,8 @@
private static final String TAG = "FingerprintDialogView";
- private static final int ANIMATION_DURATION = 250; // ms
+ private static final int ANIMATION_DURATION_SHOW = 250; // ms
+ private static final int ANIMATION_DURATION_AWAY = 350; // ms
private static final int STATE_NONE = 0;
private static final int STATE_FINGERPRINT = 1;
@@ -162,14 +163,29 @@
mLastState = STATE_NONE;
updateFingerprintIcon(STATE_FINGERPRINT);
- title.setText(mBundle.getCharSequence(FingerprintDialog.KEY_TITLE));
+ title.setText(mBundle.getCharSequence(BiometricDialog.KEY_TITLE));
title.setSelected(true);
- subtitle.setText(mBundle.getCharSequence(FingerprintDialog.KEY_SUBTITLE));
- description.setText(mBundle.getCharSequence(FingerprintDialog.KEY_DESCRIPTION));
- negative.setText(mBundle.getCharSequence(FingerprintDialog.KEY_NEGATIVE_TEXT));
+
+ final CharSequence subtitleText = mBundle.getCharSequence(BiometricDialog.KEY_SUBTITLE);
+ if (subtitleText == null) {
+ subtitle.setVisibility(View.GONE);
+ } else {
+ subtitle.setVisibility(View.VISIBLE);
+ subtitle.setText(subtitleText);
+ }
+
+ final CharSequence descriptionText = mBundle.getCharSequence(BiometricDialog.KEY_DESCRIPTION);
+ if (descriptionText == null) {
+ subtitle.setVisibility(View.VISIBLE);
+ description.setVisibility(View.GONE);
+ } else {
+ description.setText(mBundle.getCharSequence(BiometricDialog.KEY_DESCRIPTION));
+ }
+
+ negative.setText(mBundle.getCharSequence(BiometricDialog.KEY_NEGATIVE_TEXT));
final CharSequence positiveText =
- mBundle.getCharSequence(FingerprintDialog.KEY_POSITIVE_TEXT);
+ mBundle.getCharSequence(BiometricDialog.KEY_POSITIVE_TEXT);
positive.setText(positiveText); // needs to be set for marquee to work
if (positiveText != null) {
positive.setVisibility(View.VISIBLE);
@@ -185,13 +201,13 @@
public void run() {
mLayout.animate()
.alpha(1f)
- .setDuration(ANIMATION_DURATION)
+ .setDuration(ANIMATION_DURATION_SHOW)
.setInterpolator(mLinearOutSlowIn)
.withLayer()
.start();
mDialog.animate()
.translationY(0)
- .setDuration(ANIMATION_DURATION)
+ .setDuration(ANIMATION_DURATION_SHOW)
.setInterpolator(mLinearOutSlowIn)
.withLayer()
.start();
@@ -221,13 +237,13 @@
public void run() {
mLayout.animate()
.alpha(0f)
- .setDuration(ANIMATION_DURATION)
+ .setDuration(ANIMATION_DURATION_AWAY)
.setInterpolator(mLinearOutSlowIn)
.withLayer()
.start();
mDialog.animate()
.translationY(mAnimationTranslationOffset)
- .setDuration(ANIMATION_DURATION)
+ .setDuration(ANIMATION_DURATION_AWAY)
.setInterpolator(mLinearOutSlowIn)
.withLayer()
.withEndAction(endActionRunnable)
@@ -255,7 +271,7 @@
mErrorText.setTextColor(mErrorTextColor);
mErrorText.setContentDescription(message);
mHandler.sendMessageDelayed(mHandler.obtainMessage(FingerprintDialogImpl.MSG_CLEAR_MESSAGE),
- FingerprintDialog.HIDE_DIALOG_DELAY);
+ BiometricDialog.HIDE_DIALOG_DELAY);
}
public void showHelpMessage(String message) {
@@ -265,7 +281,7 @@
public void showErrorMessage(String error) {
showTemporaryMessage(error);
mHandler.sendMessageDelayed(mHandler.obtainMessage(FingerprintDialogImpl.MSG_HIDE_DIALOG,
- false /* userCanceled */), FingerprintDialog.HIDE_DIALOG_DELAY);
+ false /* userCanceled */), BiometricDialog.HIDE_DIALOG_DELAY);
}
private void updateFingerprintIcon(int newState) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index a1b17e4..d6e59c7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -27,7 +27,6 @@
import android.app.ActivityManager;
import android.app.AlarmManager;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.app.trust.TrustManager;
@@ -235,6 +234,9 @@
// answer whether the input should be restricted)
private boolean mShowing;
+ // AOD is enabled and status bar is in AOD state.
+ private boolean mAodShowing;
+
// display id of the secondary display on which we have put a keyguard window
private int mSecondaryDisplayShowing = INVALID_DISPLAY;
@@ -664,7 +666,7 @@
@Override
public void onSecondaryDisplayShowingChanged(int displayId) {
synchronized (KeyguardViewMediator.this) {
- setShowingLocked(mShowing, displayId, false);
+ setShowingLocked(mShowing, mAodShowing, displayId, false);
}
}
};
@@ -707,10 +709,10 @@
setShowingLocked(!shouldWaitForProvisioning()
&& !mLockPatternUtils.isLockScreenDisabled(
KeyguardUpdateMonitor.getCurrentUser()),
- mSecondaryDisplayShowing, true /* forceCallbacks */);
+ mAodShowing, mSecondaryDisplayShowing, true /* forceCallbacks */);
} else {
// The system's keyguard is disabled or missing.
- setShowingLocked(false, mSecondaryDisplayShowing, true);
+ setShowingLocked(false, mAodShowing, mSecondaryDisplayShowing, true);
}
mStatusBarKeyguardViewManager =
@@ -1311,7 +1313,7 @@
if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) {
if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
// Without this, settings is not enabled until the lock screen first appears
- setShowingLocked(false);
+ setShowingLocked(false, mAodShowing);
hideLocked();
return;
}
@@ -1713,10 +1715,12 @@
playSound(mTrustedSoundId);
}
- private void updateActivityLockScreenState(boolean showing, int secondaryDisplayShowing) {
+ private void updateActivityLockScreenState(boolean showing, boolean aodShowing,
+ int secondaryDisplayShowing) {
mUiOffloadThread.submit(() -> {
try {
- ActivityManager.getService().setLockScreenShown(showing, secondaryDisplayShowing);
+ ActivityManager.getService().setLockScreenShown(showing, aodShowing,
+ secondaryDisplayShowing);
} catch (RemoteException e) {
}
});
@@ -1740,7 +1744,7 @@
if (DEBUG) Log.d(TAG, "handleShow");
}
- setShowingLocked(true);
+ setShowingLocked(true, mAodShowing);
mStatusBarKeyguardViewManager.show(options);
mHiding = false;
mWakeAndUnlocking = false;
@@ -1849,7 +1853,7 @@
}
mWakeAndUnlocking = false;
- setShowingLocked(false);
+ setShowingLocked(false, mAodShowing);
mDismissCallbackRegistry.notifyDismissSucceeded();
mStatusBarKeyguardViewManager.hide(startTime, fadeoutDuration);
resetKeyguardDonePendingLocked();
@@ -1909,7 +1913,7 @@
Trace.beginSection("KeyguardViewMediator#handleVerifyUnlock");
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
- setShowingLocked(true);
+ setShowingLocked(true, mAodShowing);
mStatusBarKeyguardViewManager.dismissAndCollapse();
}
Trace.endSection();
@@ -2064,6 +2068,10 @@
pw.print(" mDrawnCallback: "); pw.println(mDrawnCallback);
}
+ public void setAodShowing(boolean aodShowing) {
+ setShowingLocked(mShowing, aodShowing);
+ }
+
private static class StartKeyguardExitAnimParams {
long startTime;
@@ -2075,20 +2083,23 @@
}
}
- private void setShowingLocked(boolean showing) {
- setShowingLocked(showing, mSecondaryDisplayShowing, false /* forceCallbacks */);
+ private void setShowingLocked(boolean showing, boolean aodShowing) {
+ setShowingLocked(showing, aodShowing, mSecondaryDisplayShowing,
+ false /* forceCallbacks */);
}
- private void setShowingLocked(
- boolean showing, int secondaryDisplayShowing, boolean forceCallbacks) {
- final boolean notifyDefaultDisplayCallbacks = showing != mShowing || forceCallbacks;
+ private void setShowingLocked(boolean showing, boolean aodShowing, int secondaryDisplayShowing,
+ boolean forceCallbacks) {
+ final boolean notifyDefaultDisplayCallbacks = showing != mShowing
+ || aodShowing != mAodShowing || forceCallbacks;
if (notifyDefaultDisplayCallbacks || secondaryDisplayShowing != mSecondaryDisplayShowing) {
mShowing = showing;
+ mAodShowing = aodShowing;
mSecondaryDisplayShowing = secondaryDisplayShowing;
if (notifyDefaultDisplayCallbacks) {
notifyDefaultDisplayCallbacks(showing);
}
- updateActivityLockScreenState(showing, secondaryDisplayShowing);
+ updateActivityLockScreenState(showing, aodShowing, secondaryDisplayShowing);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 8d93157..49b00ce 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -21,9 +21,6 @@
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioAttributes;
@@ -52,15 +49,18 @@
private static final String TAG_BATTERY = "low_battery";
private static final String TAG_TEMPERATURE = "high_temp";
+ private static final String TAG_AUTO_SAVER = "auto_saver";
private static final int SHOWING_NOTHING = 0;
private static final int SHOWING_WARNING = 1;
private static final int SHOWING_INVALID_CHARGER = 3;
+ private static final int SHOWING_AUTO_SAVER_SUGGESTION = 4;
private static final String[] SHOWING_STRINGS = {
"SHOWING_NOTHING",
"SHOWING_WARNING",
"SHOWING_SAVER",
"SHOWING_INVALID_CHARGER",
+ "SHOWING_AUTO_SAVER_SUGGESTION",
};
private static final String ACTION_SHOW_BATTERY_SETTINGS = "PNW.batterySettings";
@@ -74,6 +74,18 @@
"PNW.dismissedThermalShutdownWarning";
private static final String ACTION_SHOW_START_SAVER_CONFIRMATION =
BatterySaverUtils.ACTION_SHOW_START_SAVER_CONFIRMATION;
+ private static final String ACTION_SHOW_AUTO_SAVER_SUGGESTION =
+ BatterySaverUtils.ACTION_SHOW_AUTO_SAVER_SUGGESTION;
+ private static final String ACTION_DISMISS_AUTO_SAVER_SUGGESTION =
+ "PNW.dismissAutoSaverSuggestion";
+
+ private static final String ACTION_ENABLE_AUTO_SAVER =
+ "PNW.enableAutoSaver";
+ private static final String ACTION_AUTO_SAVER_NO_THANKS =
+ "PNW.autoSaverNoThanks";
+
+ private static final String SETTINGS_ACTION_OPEN_BATTERY_SAVER_SETTING =
+ "android.settings.BATTERY_SAVER_SETTINGS";
private static final AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
@@ -98,9 +110,11 @@
private long mLowWarningThreshold;
private long mSevereWarningThreshold;
private boolean mWarning;
+ private boolean mShowAutoSaverSuggestion;
private boolean mPlaySound;
private boolean mInvalidCharger;
private SystemUIDialog mSaverConfirmation;
+ private SystemUIDialog mSaverEnabledConfirmation;
private boolean mHighTempWarning;
private SystemUIDialog mHighTempDialog;
private SystemUIDialog mThermalShutdownDialog;
@@ -119,12 +133,19 @@
pw.print("mInvalidCharger="); pw.println(mInvalidCharger);
pw.print("mShowing="); pw.println(SHOWING_STRINGS[mShowing]);
pw.print("mSaverConfirmation="); pw.println(mSaverConfirmation != null ? "not null" : null);
+ pw.print("mSaverEnabledConfirmation=");
+ pw.println(mSaverEnabledConfirmation != null ? "not null" : null);
pw.print("mHighTempWarning="); pw.println(mHighTempWarning);
pw.print("mHighTempDialog="); pw.println(mHighTempDialog != null ? "not null" : null);
pw.print("mThermalShutdownDialog=");
pw.println(mThermalShutdownDialog != null ? "not null" : null);
}
+ private int getLowBatteryAutoTriggerDefaultLevel() {
+ return mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_lowBatteryAutoTriggerDefaultLevel);
+ }
+
@Override
public void update(int batteryLevel, int bucket, long screenOffTime) {
mBatteryLevel = batteryLevel;
@@ -151,7 +172,6 @@
mSevereWarningThreshold = severeThreshold;
}
-
private void updateNotification() {
if (DEBUG) Slog.d(TAG, "updateNotification mWarning=" + mWarning + " mPlaySound="
+ mPlaySound + " mInvalidCharger=" + mInvalidCharger);
@@ -161,9 +181,14 @@
} else if (mWarning) {
showWarningNotification();
mShowing = SHOWING_WARNING;
+ } else if (mShowAutoSaverSuggestion) {
+ showAutoSaverSuggestionNotification();
+ mShowing = SHOWING_AUTO_SAVER_SUGGESTION;
} else {
mNoMan.cancelAsUser(TAG_BATTERY, SystemMessage.NOTE_BAD_CHARGER, UserHandle.ALL);
mNoMan.cancelAsUser(TAG_BATTERY, SystemMessage.NOTE_POWER_LOW, UserHandle.ALL);
+ mNoMan.cancelAsUser(TAG_AUTO_SAVER,
+ SystemMessage.NOTE_AUTO_SAVER_SUGGESTION, UserHandle.ALL);
mShowing = SHOWING_NOTHING;
}
}
@@ -229,6 +254,28 @@
mNoMan.notifyAsUser(TAG_BATTERY, SystemMessage.NOTE_POWER_LOW, n, UserHandle.ALL);
}
+ private void showAutoSaverSuggestionNotification() {
+ final Notification.Builder nb =
+ new Notification.Builder(mContext, NotificationChannels.HINTS)
+ .setSmallIcon(R.drawable.ic_power_saver)
+ .setWhen(0)
+ .setShowWhen(false)
+ .setContentTitle(mContext.getString(R.string.auto_saver_title))
+ .setContentText(mContext.getString(R.string.auto_saver_text,
+ getLowBatteryAutoTriggerDefaultLevel()));
+ nb.setContentIntent(pendingBroadcast(ACTION_ENABLE_AUTO_SAVER));
+ nb.setDeleteIntent(pendingBroadcast(ACTION_DISMISS_AUTO_SAVER_SUGGESTION));
+ nb.addAction(0,
+ mContext.getString(R.string.no_auto_saver_action),
+ pendingBroadcast(ACTION_AUTO_SAVER_NO_THANKS));
+
+ SystemUI.overrideNotificationAppName(mContext, nb, false);
+
+ final Notification n = nb.build();
+ mNoMan.notifyAsUser(
+ TAG_AUTO_SAVER, SystemMessage.NOTE_AUTO_SAVER_SUGGESTION, n, UserHandle.ALL);
+ }
+
private String getHybridContentString(String percentage) {
return PowerUtil.getBatteryRemainingStringFormatted(
mContext,
@@ -238,8 +285,8 @@
}
private PendingIntent pendingBroadcast(String action) {
- return PendingIntent.getBroadcastAsUser(mContext,
- 0, new Intent(action), 0, UserHandle.CURRENT);
+ return PendingIntent.getBroadcastAsUser(mContext, 0,
+ new Intent(action).setPackage(mContext.getPackageName()), 0, UserHandle.CURRENT);
}
private static Intent settings(String action) {
@@ -394,6 +441,16 @@
updateNotification();
}
+ private void showAutoSaverSuggestion() {
+ mShowAutoSaverSuggestion = true;
+ updateNotification();
+ }
+
+ private void dismissAutoSaverSuggestion() {
+ mShowAutoSaverSuggestion = false;
+ updateNotification();
+ }
+
@Override
public void userSwitched() {
updateNotification();
@@ -405,22 +462,53 @@
d.setTitle(R.string.battery_saver_confirmation_title);
d.setMessage(com.android.internal.R.string.battery_saver_description);
d.setNegativeButton(android.R.string.cancel, null);
- d.setPositiveButton(R.string.battery_saver_confirmation_ok, mStartSaverModeNoConfirmation);
+ d.setPositiveButton(R.string.battery_saver_confirmation_ok,
+ (dialog, which) -> setSaverMode(true, false));
d.setShowForAllUsers(true);
- d.setOnDismissListener(new OnDismissListener() {
- @Override
- public void onDismiss(DialogInterface dialog) {
- mSaverConfirmation = null;
- }
- });
+ d.setOnDismissListener((dialog) -> mSaverConfirmation = null);
d.show();
mSaverConfirmation = d;
}
+ private void showAutoSaverEnabledConfirmation() {
+ if (mSaverEnabledConfirmation != null) return;
+
+ // Open the Battery Saver setting page.
+ final Intent actionBatterySaverSetting =
+ new Intent(SETTINGS_ACTION_OPEN_BATTERY_SAVER_SETTING)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ final SystemUIDialog d = new SystemUIDialog(mContext);
+ d.setTitle(R.string.auto_saver_enabled_title);
+ d.setMessage(mContext.getString(R.string.auto_saver_enabled_text,
+ getLowBatteryAutoTriggerDefaultLevel()));
+
+ // Negative == "got it". Just close the dialog. Battery saver has already been enabled.
+ d.setNegativeButton(R.string.auto_saver_okay_action, null);
+ d.setPositiveButton(R.string.open_saver_setting_action, (dialog, which) ->
+ mContext.startActivity(actionBatterySaverSetting));
+ d.setShowForAllUsers(true);
+ d.setOnDismissListener((dialog) -> mSaverEnabledConfirmation = null);
+ d.show();
+ mSaverEnabledConfirmation = d;
+ }
+
+
private void setSaverMode(boolean mode, boolean needFirstTimeWarning) {
BatterySaverUtils.setPowerSaveMode(mContext, mode, needFirstTimeWarning);
}
+ private void scheduleAutoBatterySaver() {
+ int autoTriggerThreshold = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_lowBatteryWarningLevel);
+ if (autoTriggerThreshold == 0) {
+ autoTriggerThreshold = 15;
+ }
+
+ BatterySaverUtils.scheduleAutoBatterySaver(mContext, autoTriggerThreshold);
+ showAutoSaverEnabledConfirmation();
+ }
+
private final class Receiver extends BroadcastReceiver {
public void init() {
@@ -433,6 +521,9 @@
filter.addAction(ACTION_CLICKED_THERMAL_SHUTDOWN_WARNING);
filter.addAction(ACTION_DISMISSED_THERMAL_SHUTDOWN_WARNING);
filter.addAction(ACTION_SHOW_START_SAVER_CONFIRMATION);
+ filter.addAction(ACTION_SHOW_AUTO_SAVER_SUGGESTION);
+ filter.addAction(ACTION_ENABLE_AUTO_SAVER);
+ filter.addAction(ACTION_AUTO_SAVER_NO_THANKS);
mContext.registerReceiverAsUser(this, UserHandle.ALL, filter,
android.Manifest.permission.DEVICE_POWER, mHandler);
}
@@ -462,10 +553,17 @@
showThermalShutdownDialog();
} else if (ACTION_DISMISSED_THERMAL_SHUTDOWN_WARNING.equals(action)) {
dismissThermalShutdownWarning();
+ } else if (ACTION_SHOW_AUTO_SAVER_SUGGESTION.equals(action)) {
+ showAutoSaverSuggestion();
+ } else if (ACTION_DISMISS_AUTO_SAVER_SUGGESTION.equals(action)) {
+ dismissAutoSaverSuggestion();
+ } else if (ACTION_ENABLE_AUTO_SAVER.equals(action)) {
+ dismissAutoSaverSuggestion();
+ scheduleAutoBatterySaver();
+ } else if (ACTION_AUTO_SAVER_NO_THANKS.equals(action)) {
+ dismissAutoSaverSuggestion();
+ BatterySaverUtils.suppressAutoBatterySaver(context);
}
}
}
-
- private final OnClickListener mStartSaverModeNoConfirmation =
- (dialog, which) -> setSaverMode(true, false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index bfbfbf6..7161463 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -18,17 +18,15 @@
import android.content.Context;
import android.content.res.Configuration;
-import android.graphics.Canvas;
-import android.graphics.Path;
import android.graphics.Point;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.qs.customize.QSCustomizer;
-import com.android.systemui.statusbar.ExpandableOutlineView;
/**
* Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader}
@@ -44,7 +42,11 @@
protected float mQsExpansion;
private QSCustomizer mQSCustomizer;
private View mQSFooter;
+
private View mBackground;
+ private View mBackgroundGradient;
+ private View mStatusBarBackground;
+
private int mSideMargins;
public QSContainerImpl(Context context, AttributeSet attrs) {
@@ -60,6 +62,8 @@
mQSCustomizer = findViewById(R.id.qs_customize);
mQSFooter = findViewById(R.id.qs_footer);
mBackground = findViewById(R.id.quick_settings_background);
+ mStatusBarBackground = findViewById(R.id.quick_settings_status_bar_background);
+ mBackgroundGradient = findViewById(R.id.quick_settings_gradient_view);
mSideMargins = getResources().getDimensionPixelSize(R.dimen.notification_side_paddings);
setClickable(true);
@@ -68,6 +72,22 @@
}
@Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ // Hide the backgrounds when in landscape mode.
+ if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ mBackgroundGradient.setVisibility(View.INVISIBLE);
+ mStatusBarBackground.setVisibility(View.INVISIBLE);
+ } else {
+ mBackgroundGradient.setVisibility(View.VISIBLE);
+ mStatusBarBackground.setVisibility(View.VISIBLE);
+ }
+
+ updateResources();
+ }
+
+ @Override
public boolean performClick() {
// Want to receive clicks so missing QQS tiles doesn't cause collapse, but
// don't want to do anything with them.
@@ -101,6 +121,14 @@
updateExpansion();
}
+ private void updateResources() {
+ LayoutParams layoutParams = (LayoutParams) mQSPanel.getLayoutParams();
+ layoutParams.topMargin = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.quick_qs_offset_height);
+
+ mQSPanel.setLayoutParams(layoutParams);
+ }
+
/**
* Overrides the height of this view (post-layout), so that the content is clipped to that
* height and the background is set to that height.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 9792e41..eb779a5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Handler;
@@ -52,8 +53,10 @@
import com.android.systemui.statusbar.phone.PhoneStatusBarView;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
+import com.android.systemui.statusbar.policy.Clock;
import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
+import com.android.systemui.statusbar.policy.DateView;
import com.android.systemui.statusbar.policy.NextAlarmController;
import java.util.Locale;
@@ -88,6 +91,7 @@
private TouchAnimator mStatusIconsAlphaAnimator;
private TouchAnimator mHeaderTextContainerAlphaAnimator;
+ private View mSystemIconsView;
private View mQuickQsStatusIcons;
private View mDate;
private View mHeaderTextContainerView;
@@ -97,6 +101,9 @@
private View mLongPressTooltipView;
/** {@link TextView} containing the actual text indicating when the next alarm will go off. */
private TextView mNextAlarmTextView;
+ private BatteryMeterView mBatteryMeterView;
+ private Clock mClockView;
+ private DateView mDateView;
private NextAlarmController mAlarmController;
private String mNextAlarmText;
@@ -122,6 +129,7 @@
mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
mDate = findViewById(R.id.date);
mDate.setOnClickListener(this);
+ mSystemIconsView = findViewById(R.id.quick_status_bar_system_icons);
mQuickQsStatusIcons = findViewById(R.id.quick_qs_status_icons);
mIconManager = new TintedIconManager(findViewById(R.id.statusIcons));
@@ -145,8 +153,10 @@
// Set the correct tint for the status icons so they contrast
mIconManager.setTint(fillColor);
- BatteryMeterView battery = findViewById(R.id.battery);
- battery.setForceShowPercent(true);
+ mBatteryMeterView = findViewById(R.id.battery);
+ mBatteryMeterView.setForceShowPercent(true);
+ mClockView = findViewById(R.id.clock);
+ mDateView = findViewById(R.id.date);
}
private void applyDarkness(int id, Rect tintArea, float intensity, int color) {
@@ -167,6 +177,13 @@
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
updateResources();
+
+ // Update color schemes in landscape to use wallpaperTextColor
+ boolean shouldUseWallpaperTextColor =
+ newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;
+ mBatteryMeterView.useWallpaperTextColor(shouldUseWallpaperTextColor);
+ mClockView.useWallpaperTextColor(shouldUseWallpaperTextColor);
+ mDateView.useWallpaperTextColor(shouldUseWallpaperTextColor);
}
@Override
@@ -176,11 +193,21 @@
}
private void updateResources() {
- // Update height, especially due to landscape mode restricting space.
+ Resources resources = mContext.getResources();
+
+ // Update height for a few views, especially due to landscape mode restricting space.
mHeaderTextContainerView.getLayoutParams().height =
- mContext.getResources().getDimensionPixelSize(R.dimen.qs_header_tooltip_height);
+ resources.getDimensionPixelSize(R.dimen.qs_header_tooltip_height);
mHeaderTextContainerView.setLayoutParams(mHeaderTextContainerView.getLayoutParams());
+ mSystemIconsView.getLayoutParams().height = resources.getDimensionPixelSize(
+ com.android.internal.R.dimen.quick_qs_offset_height);
+ mSystemIconsView.setLayoutParams(mSystemIconsView.getLayoutParams());
+
+ getLayoutParams().height =
+ resources.getDimensionPixelSize(com.android.internal.R.dimen.quick_qs_total_height);
+ setLayoutParams(getLayoutParams());
+
updateStatusIconAlphaAnimator();
updateHeaderTextContainerAlphaAnimator();
}
@@ -449,9 +476,8 @@
mHeaderQsPanel.setHost(host, null /* No customization in header */);
// Use SystemUI context to get battery meter colors, and let it use the default tint (white)
- BatteryMeterView battery = findViewById(R.id.battery);
- battery.setColorsFromContext(mHost.getContext());
- battery.onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
+ mBatteryMeterView.setColorsFromContext(mHost.getContext());
+ mBatteryMeterView.onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
}
public void setCallback(Callback qsPanelCallback) {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 1596d12..3d8e037 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -592,7 +592,16 @@
// Record last snap target the divider moved to
if (mHomeStackResizable && !mIsInMinimizeInteraction) {
- saveSnapTargetBeforeMinimized(snapTarget);
+ // The last snapTarget position can be negative when the last divider position was
+ // offscreen. In that case, save the middle (default) SnapTarget so calculating next
+ // position isn't negative.
+ final SnapTarget saveTarget;
+ if (snapTarget.position < 0) {
+ saveTarget = mSnapAlgorithm.getMiddleTarget();
+ } else {
+ saveTarget = snapTarget;
+ }
+ saveSnapTargetBeforeMinimized(saveTarget);
}
};
Runnable notCancelledEndAction = () -> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index fa177f2..65037f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -18,7 +18,7 @@
import android.content.ComponentName;
import android.graphics.Rect;
-import android.hardware.fingerprint.IFingerprintDialogReceiver;
+import android.hardware.biometrics.IBiometricDialogReceiver;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -160,7 +160,7 @@
default void onRotationProposal(int rotation, boolean isValid) { }
- default void showFingerprintDialog(Bundle bundle, IFingerprintDialogReceiver receiver) { }
+ default void showFingerprintDialog(Bundle bundle, IBiometricDialogReceiver receiver) { }
default void onFingerprintAuthenticated() { }
default void onFingerprintHelp(String message) { }
default void onFingerprintError(String error) { }
@@ -513,7 +513,7 @@
}
@Override
- public void showFingerprintDialog(Bundle bundle, IFingerprintDialogReceiver receiver) {
+ public void showFingerprintDialog(Bundle bundle, IBiometricDialogReceiver receiver) {
synchronized (mLock) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = bundle;
@@ -759,7 +759,7 @@
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).showFingerprintDialog(
(Bundle)((SomeArgs)msg.obj).arg1,
- (IFingerprintDialogReceiver)((SomeArgs)msg.obj).arg2);
+ (IBiometricDialogReceiver)((SomeArgs)msg.obj).arg2);
}
break;
case MSG_FINGERPRINT_AUTHENTICATED:
@@ -810,4 +810,3 @@
}
}
}
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index ebc7b94..05a5a8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar;
+import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
import static com.android.systemui.statusbar.notification.NotificationInflater.InflationCallback;
@@ -34,7 +35,6 @@
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
-import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.ArraySet;
import android.util.AttributeSet;
@@ -127,6 +127,8 @@
private boolean mHasUserChangedExpansion;
/** If {@link #mHasUserChangedExpansion}, has the user expanded this row */
private boolean mUserExpanded;
+ /** Whether the blocking helper is showing on this notification (even if dismissed) */
+ private boolean mIsBlockingHelperShowing;
/**
* Has this notification been expanded while it was pinned
@@ -400,8 +402,7 @@
updateIconVisibilities();
updateShelfIconColor();
- showBlockingHelper(mEntry.userSentiment ==
- NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
+ showBlockingHelperButton(mEntry.userSentiment == USER_SENTIMENT_NEGATIVE);
updateRippleAllowed();
}
@@ -594,6 +595,13 @@
return mNotificationParent != null;
}
+ /**
+ * @return whether this notification is the only child in the group summary
+ */
+ public boolean isOnlyChildInGroup() {
+ return mGroupManager.isOnlyChildInGroup(getStatusBarNotification());
+ }
+
public ExpandableNotificationRow getNotificationParent() {
return mNotificationParent;
}
@@ -1150,11 +1158,31 @@
return mGroupParentWhenDismissed;
}
+ /**
+ * Dismisses the notification with the option of showing the blocking helper in-place if we have
+ * a negative user sentiment.
+ *
+ * @param fromAccessibility whether this dismiss is coming from an accessibility action
+ * @return whether a blocking helper is shown in this row
+ */
+ public boolean performDismissWithBlockingHelper(boolean fromAccessibility) {
+ NotificationBlockingHelperManager manager =
+ Dependency.get(NotificationBlockingHelperManager.class);
+ boolean isBlockingHelperShown = manager.perhapsShowBlockingHelper(this, mMenuRow);
+
+ // Continue with dismiss since we don't want the blocking helper to be directly associated
+ // with a certain notification.
+ performDismiss(fromAccessibility);
+ return isBlockingHelperShown;
+ }
+
public void performDismiss(boolean fromAccessibility) {
- if (mGroupManager.isOnlyChildInGroup(getStatusBarNotification())) {
+ if (isOnlyChildInGroup()) {
ExpandableNotificationRow groupSummary =
mGroupManager.getLogicalGroupSummary(getStatusBarNotification());
if (groupSummary.isClearable()) {
+ // If this is the only child in the group, dismiss the group, but don't try to show
+ // the blocking helper affordance!
groupSummary.performDismiss(fromAccessibility);
}
}
@@ -1166,6 +1194,14 @@
}
}
+ public void setBlockingHelperShowing(boolean isBlockingHelperShowing) {
+ mIsBlockingHelperShowing = isBlockingHelperShowing;
+ }
+
+ public boolean isBlockingHelperShowing() {
+ return mIsBlockingHelperShowing;
+ }
+
public void setOnDismissRunnable(Runnable onDismissRunnable) {
mOnDismissRunnable = onDismissRunnable;
}
@@ -1390,7 +1426,7 @@
requestLayout();
}
- public void showBlockingHelper(boolean show) {
+ public void showBlockingHelperButton(boolean show) {
mHelperButton.setVisibility(show ? View.VISIBLE : View.GONE);
}
@@ -1423,7 +1459,6 @@
mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
mLayouts = new NotificationContentView[] {mPrivateLayout, mPublicLayout};
- final NotificationGutsManager gutsMan = Dependency.get(NotificationGutsManager.class);
mHelperButton = findViewById(R.id.helper);
mHelperButton.setOnClickListener(view -> {
doLongClickCallback();
@@ -2526,7 +2561,7 @@
}
switch (action) {
case AccessibilityNodeInfo.ACTION_DISMISS:
- performDismiss(true /* fromAccessibility */);
+ performDismissWithBlockingHelper(true /* fromAccessibility */);
return true;
case AccessibilityNodeInfo.ACTION_COLLAPSE:
case AccessibilityNodeInfo.ACTION_EXPAND:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBlockingHelperManager.java
new file mode 100644
index 0000000..c9c1bc6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBlockingHelperManager.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.support.annotation.VisibleForTesting;
+import android.util.Log;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+
+import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
+
+/**
+ * Manager for the notification blocking helper - tracks and helps create the blocking helper
+ * affordance.
+ */
+public class NotificationBlockingHelperManager {
+ /** Enables debug logging and always makes the blocking helper show up after a dismiss. */
+ private static final boolean DEBUG = false;
+ private static final String TAG = "BlockingHelper";
+
+ private final Context mContext;
+ /** Row that the blocking helper will be shown in (via {@link NotificationGuts}. */
+ private ExpandableNotificationRow mBlockingHelperRow;
+
+ /**
+ * Whether the notification shade/stack is expanded - used to determine blocking helper
+ * eligibility.
+ */
+ private boolean mIsShadeExpanded;
+
+ public NotificationBlockingHelperManager(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Potentially shows the blocking helper, represented via the {@link NotificationInfo} menu
+ * item, in the current row if user sentiment is negative.
+ *
+ * @param row row to render the blocking helper in
+ * @param menuRow menu used to generate the {@link NotificationInfo} view that houses the
+ * blocking helper UI
+ * @return whether we're showing a blocking helper in the given notification row
+ */
+ boolean perhapsShowBlockingHelper(
+ ExpandableNotificationRow row, NotificationMenuRowPlugin menuRow) {
+ int numChildren = row.getNumberOfNotificationChildren();
+
+ // We only show the blocking helper if:
+ // - The dismissed row is a valid group (>1 or 0 children) or the only child in the group
+ // - The notification shade is fully expanded (guarantees we're not touching a HUN).
+ // - User sentiment is negative
+ if (DEBUG
+ || row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE
+ && mIsShadeExpanded
+ && (!row.isChildInGroup() || row.isOnlyChildInGroup())) {
+ // Dismiss any current blocking helper before continuing forward (only one can be shown
+ // at a given time).
+ dismissCurrentBlockingHelper();
+
+ if (DEBUG) {
+ Log.d(TAG, "Manager.perhapsShowBlockingHelper: Showing new blocking helper");
+ }
+ NotificationGutsManager manager = Dependency.get(NotificationGutsManager.class);
+
+ // Enable blocking helper on the row before moving forward so everything in the guts is
+ // correctly prepped.
+ mBlockingHelperRow = row;
+ mBlockingHelperRow.setBlockingHelperShowing(true);
+
+ // We don't care about the touch origin (x, y) since we're opening guts without any
+ // explicit user interaction.
+ manager.openGuts(mBlockingHelperRow, 0, 0, menuRow.getLongpressMenuItem(mContext));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Dismiss the currently showing blocking helper, if any, through a notification update.
+ *
+ * @return whether the blocking helper was dismissed
+ */
+ boolean dismissCurrentBlockingHelper() {
+ if (!isBlockingHelperRowNull()) {
+ if (DEBUG) {
+ Log.d(TAG, "Manager.dismissCurrentBlockingHelper: Dismissing current helper");
+ }
+ if (!mBlockingHelperRow.isBlockingHelperShowing()) {
+ Log.e(TAG, "Manager.dismissCurrentBlockingHelper: "
+ + "Non-null row is not showing a blocking helper");
+ }
+
+ mBlockingHelperRow.setBlockingHelperShowing(false);
+ if (mBlockingHelperRow.isAttachedToWindow()) {
+ Dependency.get(NotificationEntryManager.class).updateNotifications();
+ }
+ mBlockingHelperRow = null;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Update the expansion status of the notification shade/stack.
+ *
+ * @param expandedHeight how much the shade is expanded ({code 0} indicating it's collapsed)
+ */
+ public void setNotificationShadeExpanded(float expandedHeight) {
+ mIsShadeExpanded = expandedHeight > 0.0f;
+ }
+
+ @VisibleForTesting
+ boolean isBlockingHelperRowNull() {
+ return mBlockingHelperRow == null;
+ }
+
+ @VisibleForTesting
+ void setBlockingHelperRowForTest(ExpandableNotificationRow blockingHelperRowForTest) {
+ mBlockingHelperRow = blockingHelperRowForTest;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 52776d7..bc572a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -30,6 +30,7 @@
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
+import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.stack.StackStateAnimator;
@@ -189,8 +190,12 @@
}
public void openControls(
- int x, int y, boolean needsFalsingProtection, @Nullable Runnable onAnimationEnd) {
- animateOpen(x, y, onAnimationEnd);
+ boolean shouldDoCircularReveal,
+ int x,
+ int y,
+ boolean needsFalsingProtection,
+ @Nullable Runnable onAnimationEnd) {
+ animateOpen(shouldDoCircularReveal, x, y, onAnimationEnd);
setExposed(true /* exposed */, needsFalsingProtection);
}
@@ -204,7 +209,20 @@
}
}
+ /**
+ * Closes any exposed guts/views.
+ *
+ * @param x x coordinate to animate the close circular reveal with
+ * @param y y coordinate to animate the close circular reveal with
+ * @param save whether the state should be saved
+ * @param force whether the guts should be force-closed regardless of state.
+ */
public void closeControls(int x, int y, boolean save, boolean force) {
+ // First try to dismiss any blocking helper.
+ boolean wasBlockingHelperDismissed =
+ Dependency.get(NotificationBlockingHelperManager.class)
+ .dismissCurrentBlockingHelper();
+
if (getWindowToken() == null) {
if (mClosedListener != null) {
mClosedListener.onGutsClosed(this);
@@ -212,8 +230,12 @@
return;
}
- if (mGutsContent == null || !mGutsContent.handleCloseControls(save, force)) {
- animateClose(x, y);
+ if (mGutsContent == null
+ || !mGutsContent.handleCloseControls(save, force)
+ || wasBlockingHelperDismissed) {
+ // We only want to do a circular reveal if we're not showing the blocking helper.
+ animateClose(x, y, !wasBlockingHelperDismissed /* shouldDoCircularReveal */);
+
setExposed(false, mNeedsFalsingProtection);
if (mClosedListener != null) {
mClosedListener.onGutsClosed(this);
@@ -221,47 +243,58 @@
}
}
- private void animateOpen(int x, int y, @Nullable Runnable onAnimationEnd) {
- final double horz = Math.max(getWidth() - x, x);
- final double vert = Math.max(getHeight() - y, y);
- final float r = (float) Math.hypot(horz, vert);
-
- final Animator a
- = ViewAnimationUtils.createCircularReveal(this, x, y, 0, r);
- a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- a.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- if (onAnimationEnd != null) {
- onAnimationEnd.run();
- }
- }
- });
- a.start();
+ /** Animates in the guts view via either a fade or a circular reveal. */
+ private void animateOpen(
+ boolean shouldDoCircularReveal, int x, int y, @Nullable Runnable onAnimationEnd) {
+ if (shouldDoCircularReveal) {
+ double horz = Math.max(getWidth() - x, x);
+ double vert = Math.max(getHeight() - y, y);
+ float r = (float) Math.hypot(horz, vert);
+ // Circular reveal originating at (x, y)
+ Animator a = ViewAnimationUtils.createCircularReveal(this, x, y, 0, r);
+ a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ a.addListener(new AnimateOpenListener(onAnimationEnd));
+ a.start();
+ } else {
+ // Fade in content
+ this.setAlpha(0f);
+ this.animate()
+ .alpha(1f)
+ .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
+ .setInterpolator(Interpolators.ALPHA_IN)
+ .setListener(new AnimateOpenListener(onAnimationEnd))
+ .start();
+ }
}
- private void animateClose(int x, int y) {
- if (x == -1 || y == -1) {
- x = (getLeft() + getRight()) / 2;
- y = (getTop() + getHeight() / 2);
- }
- final double horz = Math.max(getWidth() - x, x);
- final double vert = Math.max(getHeight() - y, y);
- final float r = (float) Math.hypot(horz, vert);
- final Animator a = ViewAnimationUtils.createCircularReveal(this,
- x, y, r, 0);
- a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
- a.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- setVisibility(View.GONE);
+
+ /** Animates out the guts view via either a fade or a circular reveal. */
+ private void animateClose(int x, int y, boolean shouldDoCircularReveal) {
+ if (shouldDoCircularReveal) {
+ // Circular reveal originating at (x, y)
+ if (x == -1 || y == -1) {
+ x = (getLeft() + getRight()) / 2;
+ y = (getTop() + getHeight() / 2);
}
- });
- a.start();
+ double horz = Math.max(getWidth() - x, x);
+ double vert = Math.max(getHeight() - y, y);
+ float r = (float) Math.hypot(horz, vert);
+ Animator a = ViewAnimationUtils.createCircularReveal(this,
+ x, y, r, 0);
+ a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+ a.addListener(new AnimateCloseListener(this /* view */));
+ a.start();
+ } else {
+ // Fade in the blocking helper.
+ this.animate()
+ .alpha(0f)
+ .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
+ .setInterpolator(Interpolators.ALPHA_OUT)
+ .setListener(new AnimateCloseListener(this /* view */))
+ .start();
+ }
}
public void setActualHeight(int actualHeight) {
@@ -336,4 +369,36 @@
public boolean isLeavebehind() {
return mGutsContent != null && mGutsContent.isLeavebehind();
}
+
+ /** Listener for animations executed in {@link #animateOpen(boolean, int, int, Runnable)}. */
+ private static class AnimateOpenListener extends AnimatorListenerAdapter {
+ final Runnable mOnAnimationEnd;
+
+ private AnimateOpenListener(Runnable onAnimationEnd) {
+ mOnAnimationEnd = onAnimationEnd;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ if (mOnAnimationEnd != null) {
+ mOnAnimationEnd.run();
+ }
+ }
+ }
+
+ /** Listener for animations executed in {@link #animateClose(int, int, boolean)}. */
+ private static class AnimateCloseListener extends AnimatorListenerAdapter {
+ final View mView;
+
+ private AnimateCloseListener(View view) {
+ mView = view;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ mView.setVisibility(View.GONE);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java
index 9b2f939..75204d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java
@@ -21,7 +21,6 @@
import static android.service.notification.NotificationListenerService.Ranking
.USER_SENTIMENT_NEGATIVE;
-import android.app.AppOpsManager;
import android.app.INotificationManager;
import android.app.NotificationChannel;
import android.content.Context;
@@ -34,6 +33,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
+import android.support.annotation.VisibleForTesting;
import android.util.ArraySet;
import android.util.Log;
import android.view.HapticFeedbackConstants;
@@ -119,22 +119,6 @@
bindGuts(row);
}
- private void saveAndCloseNotificationMenu(
- ExpandableNotificationRow row, NotificationGuts guts, View done) {
- guts.resetFalsingCheck();
- int[] rowLocation = new int[2];
- int[] doneLocation = new int[2];
- row.getLocationOnScreen(rowLocation);
- done.getLocationOnScreen(doneLocation);
-
- final int centerX = done.getWidth() / 2;
- final int centerY = done.getHeight() / 2;
- final int x = doneLocation[0] - rowLocation[0] + centerX;
- final int y = doneLocation[1] - rowLocation[1] + centerY;
- closeAndSaveGuts(false /* removeLeavebehind */, false /* force */,
- true /* removeControls */, x, y, true /* resetMenu */);
- }
-
/**
* Sends an intent to open the app settings for a particular package and optional
* channel.
@@ -174,12 +158,12 @@
private void bindGuts(final ExpandableNotificationRow row,
NotificationMenuRowPlugin.MenuItem item) {
+ StatusBarNotification sbn = row.getStatusBarNotification();
+
row.inflateGuts();
row.setGutsView(item);
- final StatusBarNotification sbn = row.getStatusBarNotification();
row.setTag(sbn.getPackageName());
- final NotificationGuts guts = row.getGuts();
- guts.setClosedListener((NotificationGuts g) -> {
+ row.getGuts().setClosedListener((NotificationGuts g) -> {
if (!g.willBeRemoved() && !row.isRemoved()) {
mListContainer.onHeightChanged(
row, !mPresenter.isPresenterFullyCollapsed() /* needsAnimation */);
@@ -197,87 +181,143 @@
View gutsView = item.getGutsView();
if (gutsView instanceof NotificationSnooze) {
- NotificationSnooze snoozeGuts = (NotificationSnooze) gutsView;
- snoozeGuts.setSnoozeListener(mListContainer.getSwipeActionHelper());
- snoozeGuts.setStatusBarNotification(sbn);
- snoozeGuts.setSnoozeOptions(row.getEntry().snoozeCriteria);
- guts.setHeightChangedListener((NotificationGuts g) -> {
- mListContainer.onHeightChanged(row, row.isShown() /* needsAnimation */);
- });
+ initializeSnoozeView(row, (NotificationSnooze) gutsView);
+ } else if (gutsView instanceof AppOpsInfo) {
+ initializeAppOpsInfo(row, (AppOpsInfo) gutsView);
+ } else if (gutsView instanceof NotificationInfo) {
+ initializeNotificationInfo(row, (NotificationInfo) gutsView);
}
+ }
- if (gutsView instanceof AppOpsInfo) {
- AppOpsInfo info = (AppOpsInfo) gutsView;
- final UserHandle userHandle = sbn.getUser();
- PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
- userHandle.getIdentifier());
- final AppOpsInfo.OnSettingsClickListener onSettingsClick = (View v,
- String pkg, int uid, ArraySet<Integer> ops) -> {
- mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_OPS_GUTS_SETTINGS);
- guts.resetFalsingCheck();
- startAppOpsSettingsActivity(pkg, uid, ops, row);
- };
- if (!row.getEntry().mActiveAppOps.isEmpty()) {
- info.bindGuts(pmUser, onSettingsClick, sbn, row.getEntry().mActiveAppOps);
- }
+ /**
+ * Sets up the {@link NotificationSnooze} inside the notification row's guts.
+ *
+ * @param row view to set up the guts for
+ * @param notificationSnoozeView view to set up/bind within {@code row}
+ */
+ private void initializeSnoozeView(
+ final ExpandableNotificationRow row,
+ NotificationSnooze notificationSnoozeView) {
+ NotificationGuts guts = row.getGuts();
+ StatusBarNotification sbn = row.getStatusBarNotification();
+
+ notificationSnoozeView.setSnoozeListener(mListContainer.getSwipeActionHelper());
+ notificationSnoozeView.setStatusBarNotification(sbn);
+ notificationSnoozeView.setSnoozeOptions(row.getEntry().snoozeCriteria);
+ guts.setHeightChangedListener((NotificationGuts g) -> {
+ mListContainer.onHeightChanged(row, row.isShown() /* needsAnimation */);
+ });
+ }
+
+ /**
+ * Sets up the {@link AppOpsInfo} inside the notification row's guts.
+ *
+ * @param row view to set up the guts for
+ * @param appOpsInfoView view to set up/bind within {@code row}
+ */
+ private void initializeAppOpsInfo(
+ final ExpandableNotificationRow row,
+ AppOpsInfo appOpsInfoView) {
+ NotificationGuts guts = row.getGuts();
+ StatusBarNotification sbn = row.getStatusBarNotification();
+ UserHandle userHandle = sbn.getUser();
+ PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
+ userHandle.getIdentifier());
+
+ AppOpsInfo.OnSettingsClickListener onSettingsClick =
+ (View v, String pkg, int uid, ArraySet<Integer> ops) -> {
+ mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_OPS_GUTS_SETTINGS);
+ guts.resetFalsingCheck();
+ startAppOpsSettingsActivity(pkg, uid, ops, row);
+ };
+ if (!row.getEntry().mActiveAppOps.isEmpty()) {
+ appOpsInfoView.bindGuts(pmUser, onSettingsClick, sbn, row.getEntry().mActiveAppOps);
}
+ }
- if (gutsView instanceof NotificationInfo) {
- final UserHandle userHandle = sbn.getUser();
- PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
- userHandle.getIdentifier());
- final INotificationManager iNotificationManager = INotificationManager.Stub.asInterface(
- ServiceManager.getService(Context.NOTIFICATION_SERVICE));
- final String pkg = sbn.getPackageName();
- NotificationInfo info = (NotificationInfo) gutsView;
- // Settings link is only valid for notifications that specify a user, unless this is the
- // system user.
- NotificationInfo.OnSettingsClickListener onSettingsClick = null;
- if (!userHandle.equals(UserHandle.ALL)
- || mLockscreenUserManager.getCurrentUserId() == UserHandle.USER_SYSTEM) {
- onSettingsClick = (View v, NotificationChannel channel, int appUid) -> {
- mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_NOTE_INFO);
+ /**
+ * Sets up the {@link NotificationInfo} inside the notification row's guts.
+ *
+ * @param row view to set up the guts for
+ * @param notificationInfoView view to set up/bind within {@code row}
+ */
+ @VisibleForTesting
+ void initializeNotificationInfo(
+ final ExpandableNotificationRow row,
+ NotificationInfo notificationInfoView) {
+ NotificationGuts guts = row.getGuts();
+ StatusBarNotification sbn = row.getStatusBarNotification();
+ String packageName = sbn.getPackageName();
+ // Settings link is only valid for notifications that specify a non-system user
+ NotificationInfo.OnSettingsClickListener onSettingsClick = null;
+ UserHandle userHandle = sbn.getUser();
+ PackageManager pmUser = StatusBar.getPackageManagerForUser(
+ mContext, userHandle.getIdentifier());
+ INotificationManager iNotificationManager = INotificationManager.Stub.asInterface(
+ ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+ final NotificationInfo.OnAppSettingsClickListener onAppSettingsClick =
+ (View v, Intent intent) -> {
+ mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_APP_NOTE_SETTINGS);
guts.resetFalsingCheck();
- mOnSettingsClickListener.onClick(sbn.getKey());
- startAppNotificationSettingsActivity(pkg, appUid, channel, row);
+ mPresenter.startNotificationGutsIntent(intent, sbn.getUid(), row);
};
- }
- final NotificationInfo.OnAppSettingsClickListener onAppSettingsClick = (View v,
- Intent intent) -> {
- mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_APP_NOTE_SETTINGS);
- guts.resetFalsingCheck();
- mPresenter.startNotificationGutsIntent(intent, sbn.getUid(), row);
- };
- final View.OnClickListener onDoneClick = (View v) -> {
- saveAndCloseNotificationMenu(row, guts, v);
- };
+ boolean isForBlockingHelper = row.isBlockingHelperShowing();
- ArraySet<NotificationChannel> channels = new ArraySet<>();
- channels.add(row.getEntry().channel);
- if (row.isSummaryWithChildren()) {
- // If this is a summary, then add in the children notification channels for the
- // same user and pkg.
- final List<ExpandableNotificationRow> childrenRows = row.getNotificationChildren();
- final int numChildren = childrenRows.size();
- for (int i = 0; i < numChildren; i++) {
- final ExpandableNotificationRow childRow = childrenRows.get(i);
- final NotificationChannel childChannel = childRow.getEntry().channel;
- final StatusBarNotification childSbn = childRow.getStatusBarNotification();
- if (childSbn.getUser().equals(userHandle) &&
- childSbn.getPackageName().equals(pkg)) {
- channels.add(childChannel);
- }
+ if (!userHandle.equals(UserHandle.ALL)
+ || mLockscreenUserManager.getCurrentUserId() == UserHandle.USER_SYSTEM) {
+ onSettingsClick = (View v, NotificationChannel channel, int appUid) -> {
+ mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_NOTE_INFO);
+ guts.resetFalsingCheck();
+ mOnSettingsClickListener.onClick(sbn.getKey());
+ startAppNotificationSettingsActivity(packageName, appUid, channel, row);
+ };
+ }
+
+ try {
+ notificationInfoView.bindNotification(
+ pmUser,
+ iNotificationManager,
+ packageName,
+ row.getEntry().channel,
+ getNumNotificationChannels(row, packageName, userHandle),
+ sbn,
+ mCheckSaveListener,
+ onSettingsClick,
+ onAppSettingsClick,
+ mNonBlockablePkgs,
+ isForBlockingHelper,
+ row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ }
+
+ /**
+ * @return the number of channels covered by the notification row (including its children if
+ * it's a summary notification).
+ */
+ private int getNumNotificationChannels(
+ ExpandableNotificationRow row, String packageName, UserHandle userHandle) {
+ ArraySet<NotificationChannel> channels = new ArraySet<>();
+
+ channels.add(row.getEntry().channel);
+
+ // If this is a summary, then add in the children notification channels for the
+ // same user and pkg.
+ if (row.isSummaryWithChildren()) {
+ final List<ExpandableNotificationRow> childrenRows = row.getNotificationChildren();
+ final int numChildren = childrenRows.size();
+ for (int i = 0; i < numChildren; i++) {
+ final ExpandableNotificationRow childRow = childrenRows.get(i);
+ final NotificationChannel childChannel = childRow.getEntry().channel;
+ final StatusBarNotification childSbn = childRow.getStatusBarNotification();
+ if (childSbn.getUser().equals(userHandle) &&
+ childSbn.getPackageName().equals(packageName)) {
+ channels.add(childChannel);
}
}
- try {
- info.bindNotification(pmUser, iNotificationManager, pkg, row.getEntry().channel,
- channels.size(), sbn, mCheckSaveListener, onSettingsClick,
- onAppSettingsClick, mNonBlockablePkgs,
- row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE);
- } catch (RemoteException e) {
- Log.e(TAG, e.toString());
- }
}
+ return channels.size();
}
/**
@@ -312,37 +352,42 @@
}
/**
- * Opens guts on the given ExpandableNotificationRow |v|.
+ * Opens guts on the given ExpandableNotificationRow {@code view}. This handles opening guts for
+ * the normal half-swipe and long-press use cases via a circular reveal. When the blocking
+ * helper needs to be shown on the row, this will skip the circular reveal.
*
- * @param v ExpandableNotificationRow to open guts on
+ * @param view ExpandableNotificationRow to open guts on
* @param x x coordinate of origin of circular reveal
* @param y y coordinate of origin of circular reveal
- * @param item MenuItem the guts should display
+ * @param menuItem MenuItem the guts should display
* @return true if guts was opened
*/
- public boolean openGuts(View v, int x, int y,
- NotificationMenuRowPlugin.MenuItem item) {
- if (!(v instanceof ExpandableNotificationRow)) {
+ boolean openGuts(
+ View view,
+ int x,
+ int y,
+ NotificationMenuRowPlugin.MenuItem menuItem) {
+ if (!(view instanceof ExpandableNotificationRow)) {
return false;
}
- if (v.getWindowToken() == null) {
+ if (view.getWindowToken() == null) {
Log.e(TAG, "Trying to show notification guts, but not attached to window");
return false;
}
- final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+ final ExpandableNotificationRow row = (ExpandableNotificationRow) view;
if (row.isDark()) {
return false;
}
- v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
if (row.areGutsExposed()) {
closeAndSaveGuts(false /* removeLeavebehind */, false /* force */,
true /* removeControls */, -1 /* x */, -1 /* y */,
true /* resetMenu */);
return false;
}
- bindGuts(row, item);
+ bindGuts(row, menuItem);
NotificationGuts guts = row.getGuts();
// Assume we are a status_bar_notification_row
@@ -372,15 +417,18 @@
final boolean needsFalsingProtection =
(mPresenter.isPresenterLocked() &&
!mAccessibilityManager.isTouchExplorationEnabled());
- guts.openControls(x, y, needsFalsingProtection, () -> {
- // Move the notification view back over the menu
- row.resetTranslation();
- });
+
+ guts.openControls(
+ !row.isBlockingHelperShowing(),
+ x,
+ y,
+ needsFalsingProtection,
+ row::resetTranslation);
row.closeRemoteInput();
mListContainer.onHeightChanged(row, true /* needsAnimation */);
mNotificationGutsExposed = guts;
- mGutsMenuItem = item;
+ mGutsMenuItem = menuItem;
}
});
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index b1ad30c..a2f336e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -46,9 +46,11 @@
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.Utils;
+import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -81,11 +83,12 @@
private OnSettingsClickListener mOnSettingsClickListener;
private OnAppSettingsClickListener mAppSettingsClickListener;
private NotificationGuts mGutsContainer;
+
+ /** Whether this view is being shown as part of the blocking helper */
+ private boolean mIsForBlockingHelper;
private boolean mNegativeUserSentiment;
- private OnClickListener mOnKeepShowing = v -> {
- closeControls(v);
- };
+ private OnClickListener mOnKeepShowing = this::closeControls;
private OnClickListener mOnStopMinNotifications = v -> {
swapContent(false);
@@ -114,7 +117,9 @@
void onClick(View v, Intent intent);
}
- public void bindNotification(final PackageManager pm,
+ @VisibleForTesting
+ void bindNotification(
+ final PackageManager pm,
final INotificationManager iNotificationManager,
final String pkg,
final NotificationChannel notificationChannel,
@@ -127,20 +132,24 @@
throws RemoteException {
bindNotification(pm, iNotificationManager, pkg, notificationChannel, numChannels, sbn,
checkSaveListener, onSettingsClick, onAppSettingsClick, nonBlockablePkgs,
- false /* negative sentiment */);
+ false /* isBlockingHelper */,
+ false /* isUserSentimentNegative */);
}
- public void bindNotification(final PackageManager pm,
- final INotificationManager iNotificationManager,
- final String pkg,
- final NotificationChannel notificationChannel,
- final int numChannels,
- final StatusBarNotification sbn,
- final CheckSaveListener checkSaveListener,
- final OnSettingsClickListener onSettingsClick,
- final OnAppSettingsClickListener onAppSettingsClick,
- final Set<String> nonBlockablePkgs,
- boolean negativeUserSentiment) throws RemoteException {
+ public void bindNotification(
+ PackageManager pm,
+ INotificationManager iNotificationManager,
+ String pkg,
+ NotificationChannel notificationChannel,
+ int numChannels,
+ StatusBarNotification sbn,
+ CheckSaveListener checkSaveListener,
+ OnSettingsClickListener onSettingsClick,
+ OnAppSettingsClickListener onAppSettingsClick,
+ Set<String> nonBlockablePkgs,
+ boolean isForBlockingHelper,
+ boolean isUserSentimentNegative)
+ throws RemoteException {
mINotificationManager = iNotificationManager;
mPkg = pkg;
mNumNotificationChannels = numChannels;
@@ -152,9 +161,10 @@
mOnSettingsClickListener = onSettingsClick;
mSingleNotificationChannel = notificationChannel;
mStartingUserImportance = mChosenImportance = mSingleNotificationChannel.getImportance();
- mNegativeUserSentiment = negativeUserSentiment;
+ mNegativeUserSentiment = isUserSentimentNegative;
mIsForeground =
(mSbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
+ mIsForBlockingHelper = isForBlockingHelper;
int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
pkg, mAppUid, false /* includeDeleted */);
@@ -294,12 +304,14 @@
}
private void bindButtons() {
+ // Set up stay-in-notification actions
View block = findViewById(R.id.block);
- block.setOnClickListener(mOnStopMinNotifications);
TextView keep = findViewById(R.id.keep);
- keep.setOnClickListener(mOnKeepShowing);
- findViewById(R.id.undo).setOnClickListener(mOnUndo);
View minimize = findViewById(R.id.minimize);
+
+ findViewById(R.id.undo).setOnClickListener(mOnUndo);
+ block.setOnClickListener(mOnStopMinNotifications);
+ keep.setOnClickListener(mOnKeepShowing);
minimize.setOnClickListener(mOnStopMinNotifications);
if (mNonblockable) {
@@ -314,7 +326,7 @@
minimize.setVisibility(GONE);
}
- // app settings link
+ // Set up app settings link
TextView settingsLinkView = findViewById(R.id.app_settings);
Intent settingsIntent = getAppSettingsIntent(mPm, mPkg, mSingleNotificationChannel,
mSbn.getId(), mSbn.getTag());
@@ -421,16 +433,23 @@
return intent;
}
- private void closeControls(View v) {
- int[] parentLoc = new int[2];
- int[] targetLoc = new int[2];
- mGutsContainer.getLocationOnScreen(parentLoc);
- v.getLocationOnScreen(targetLoc);
- final int centerX = v.getWidth() / 2;
- final int centerY = v.getHeight() / 2;
- final int x = targetLoc[0] - parentLoc[0] + centerX;
- final int y = targetLoc[1] - parentLoc[1] + centerY;
- mGutsContainer.closeControls(x, y, true /* save */, false /* force */);
+ @VisibleForTesting
+ void closeControls(View v) {
+ if (mIsForBlockingHelper) {
+ NotificationBlockingHelperManager manager =
+ Dependency.get(NotificationBlockingHelperManager.class);
+ manager.dismissCurrentBlockingHelper();
+ } else {
+ int[] parentLoc = new int[2];
+ int[] targetLoc = new int[2];
+ mGutsContainer.getLocationOnScreen(parentLoc);
+ v.getLocationOnScreen(targetLoc);
+ final int centerX = v.getWidth() / 2;
+ final int centerY = v.getHeight() / 2;
+ final int x = targetLoc[0] - parentLoc[0] + centerX;
+ final int y = targetLoc[1] - parentLoc[1] + centerY;
+ mGutsContainer.closeControls(x, y, true /* save */, false /* force */);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index a4aa598..0112661 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -227,7 +227,6 @@
expandAmount = Math.min(1.0f, expandAmount);
}
// find the first view that doesn't overlap with the shelf
- int notificationIndex = 0;
int notGoneIndex = 0;
int colorOfViewBeforeLast = NO_COLOR;
boolean backgroundForceHidden = false;
@@ -247,13 +246,15 @@
int baseZHeight = mAmbientState.getBaseZHeight();
int backgroundTop = 0;
float firstElementRoundness = 0.0f;
- while (notificationIndex < mHostLayout.getChildCount()) {
- ExpandableView child = (ExpandableView) mHostLayout.getChildAt(notificationIndex);
- notificationIndex++;
+
+ for (int i = 0; i < mHostLayout.getChildCount(); i++) {
+ ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
+
if (!(child instanceof ExpandableNotificationRow)
|| child.getVisibility() == GONE) {
continue;
}
+
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
float notificationClipEnd;
boolean aboveShelf = ViewState.getFinalTranslationZ(row) > baseZHeight
@@ -315,6 +316,9 @@
notGoneIndex++;
previousColor = ownColorUntinted;
}
+
+ clipTransientViews();
+
setBackgroundTop(backgroundTop);
setFirstElementRoundness(firstElementRoundness);
mShelfIcons.setSpeedBumpIndex(mAmbientState.getSpeedBumpIndex());
@@ -337,6 +341,25 @@
}
}
+ /**
+ * Clips transient views to the top of the shelf - Transient views are only used for
+ * disappearing views/animations and need to be clipped correctly by the shelf to ensure they
+ * don't show underneath the notification stack when something is animating and the user
+ * swipes quickly.
+ */
+ private void clipTransientViews() {
+ for (int i = 0; i < mHostLayout.getTransientViewCount(); i++) {
+ View transientView = mHostLayout.getTransientView(i);
+ if (transientView instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow transientRow = (ExpandableNotificationRow) transientView;
+ updateNotificationClipHeight(transientRow, getTranslationY());
+ } else {
+ Log.e(TAG, "NotificationShelf.clipTransientViews(): "
+ + "Trying to clip non-row transient view");
+ }
+ }
+ }
+
private void setFirstElementRoundness(float firstElementRoundness) {
if (mFirstElementRoundness != firstElementRoundness) {
mFirstElementRoundness = firstElementRoundness;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 75b8b37..b1e08b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -125,24 +125,30 @@
}
- ArrayList<ExpandableNotificationRow> toRemove = new ArrayList<>();
+ ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>();
for (int i=0; i< mListContainer.getContainerChildCount(); i++) {
View child = mListContainer.getContainerChildAt(i);
if (!toShow.contains(child) && child instanceof ExpandableNotificationRow) {
- toRemove.add((ExpandableNotificationRow) child);
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+
+ // Blocking helper is effectively a detached view. Don't bother removing it from the
+ // layout.
+ if (!row.isBlockingHelperShowing()) {
+ viewsToRemove.add((ExpandableNotificationRow) child);
+ }
}
}
- for (ExpandableNotificationRow remove : toRemove) {
- if (mGroupManager.isChildInGroupWithSummary(remove.getStatusBarNotification())) {
+ for (ExpandableNotificationRow viewToRemove : viewsToRemove) {
+ if (mGroupManager.isChildInGroupWithSummary(viewToRemove.getStatusBarNotification())) {
// we are only transferring this notification to its parent, don't generate an
// animation
mListContainer.setChildTransferInProgress(true);
}
- if (remove.isSummaryWithChildren()) {
- remove.removeAllChildren();
+ if (viewToRemove.isSummaryWithChildren()) {
+ viewToRemove.removeAllChildren();
}
- mListContainer.removeContainerView(remove);
+ mListContainer.removeContainerView(viewToRemove);
mListContainer.setChildTransferInProgress(false);
}
@@ -168,6 +174,10 @@
// We don't care about non-notification views.
continue;
}
+ if (((ExpandableNotificationRow) child).isBlockingHelperShowing()) {
+ // Don't count/reorder notifications that are showing the blocking helper!
+ continue;
+ }
ExpandableNotificationRow targetChild = toShow.get(j);
if (child != targetChild) {
@@ -340,7 +350,7 @@
}
}
- row.showBlockingHelper(entry.userSentiment ==
+ row.showBlockingHelperButton(entry.userSentiment ==
NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
row.showAppOpsIcons(entry.mActiveAppOps);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index a2b1013..6576eb7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -399,4 +399,11 @@
pw.print(" mMode="); pw.println(mMode);
pw.print(" mWakeLock="); pw.println(mWakeLock);
}
+
+ public boolean isWakeAndUnlock() {
+ return mMode == MODE_UNLOCK
+ || mMode == MODE_WAKE_AND_UNLOCK
+ || mMode == MODE_WAKE_AND_UNLOCK_PULSING
+ || mMode == MODE_WAKE_AND_UNLOCK_FROM_DREAM;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index b75c7e0..ca65965 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -169,7 +169,7 @@
if (group.suppressed) {
handleSuppressedSummaryHeadsUpped(group.summary);
}
- if (!mIsUpdatingUnchangedGroup) {
+ if (!mIsUpdatingUnchangedGroup && mListener != null) {
mListener.onGroupsChanged();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 7a6e98d..4e12936 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -85,7 +85,7 @@
/**
* Default alpha value for most scrims.
*/
- public static final float GRADIENT_SCRIM_ALPHA = 0.45f;
+ public static final float GRADIENT_SCRIM_ALPHA = 0.70f;
/**
* A scrim varies its opacity based on a busyness factor, for example
* how many notifications are currently visible.
@@ -347,7 +347,9 @@
if (mExpansionFraction != fraction) {
mExpansionFraction = fraction;
- if (!(mState == ScrimState.UNLOCKED || mState == ScrimState.KEYGUARD)) {
+ final boolean keyguardOrUnlocked = mState == ScrimState.UNLOCKED
+ || mState == ScrimState.KEYGUARD;
+ if (!keyguardOrUnlocked || !mExpansionAffectsAlpha) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index 5b734eb..f4b6c38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -156,7 +156,6 @@
mCurrentBehindTint = Color.BLACK;
mBlankScreen = true;
} else {
- // Scrims should still be black at the end of the transition.
mCurrentInFrontTint = Color.TRANSPARENT;
mCurrentBehindTint = Color.TRANSPARENT;
mBlankScreen = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index ddb67df..c03ecb3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -408,6 +408,7 @@
protected NotificationEntryManager mEntryManager;
protected NotificationViewHierarchyManager mViewHierarchyManager;
protected AppOpsListener mAppOpsListener;
+ protected KeyguardViewMediator mKeyguardViewMediator;
private ZenModeController mZenController;
/**
@@ -632,6 +633,7 @@
mAppOpsListener = Dependency.get(AppOpsListener.class);
mAppOpsListener.setUpWithPresenter(this, mEntryManager);
mZenController = Dependency.get(ZenModeController.class);
+ mKeyguardViewMediator = getComponent(KeyguardViewMediator.class);
mColorExtractor = Dependency.get(SysuiColorExtractor.class);
mColorExtractor.addOnColorsChangedListener(this);
@@ -4628,6 +4630,7 @@
boolean dozing = mDozingRequested && mState == StatusBarState.KEYGUARD
|| mFingerprintUnlockController.getMode()
== FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
+ final boolean alwaysOn = DozeParameters.getInstance(mContext).getAlwaysOn();
// When in wake-and-unlock we may not have received a change to mState
// but we still should not be dozing, manually set to false.
if (mFingerprintUnlockController.getMode() ==
@@ -4635,6 +4638,7 @@
dozing = false;
}
mDozing = dozing;
+ mKeyguardViewMediator.setAodShowing(mDozing && alwaysOn);
mStatusBarWindowManager.setDozing(mDozing);
mStatusBarKeyguardViewManager.setDozing(mDozing);
if (mAmbientIndicationContainer instanceof DozeReceiver) {
@@ -4655,9 +4659,8 @@
final boolean wakeAndUnlocking = mFingerprintUnlockController.getMode()
== FingerprintUnlockController.MODE_WAKE_AND_UNLOCK;
- // Do not animate the scrim expansion when it's triggered by the fingerprint sensor.
- mScrimController.setExpansionAffectsAlpha(mFingerprintUnlockController.getMode()
- != FingerprintUnlockController.MODE_UNLOCK);
+ // Do not animate the scrim expansion when triggered by the fingerprint sensor.
+ mScrimController.setExpansionAffectsAlpha(!mFingerprintUnlockController.isWakeAndUnlock());
if (mBouncerShowing) {
// Bouncer needs the front scrim when it's on top of an activity,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 1a64b00..5975608 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -154,7 +154,7 @@
if (expansion == 1) {
mBouncer.onFullyHidden();
} else if (!mBouncer.isShowing() && !mBouncer.isAnimatingAway()) {
- mBouncer.show(true /* resetSecuritySelection */, false /* notifyFalsing */);
+ mBouncer.show(false /* resetSecuritySelection */, false /* notifyFalsing */);
} else if (noLongerTracking) {
// Notify that falsing manager should stop its session when user stops touching,
// even before the animation ends, to guarantee that we're not recording sensitive
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 309a1a7..2437c51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -143,7 +143,9 @@
final boolean scrimsOccludingWallpaper =
state.scrimsVisibility == ScrimController.VISIBILITY_FULLY_OPAQUE;
- if (state.keyguardShowing && !state.backdropShowing && !scrimsOccludingWallpaper) {
+ final boolean keyguardOrAod = state.keyguardShowing
+ || (state.dozing && mDozeParameters.getAlwaysOn());
+ if (keyguardOrAod && !state.backdropShowing && !scrimsOccludingWallpaper) {
mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
} else {
mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 4c92d01..baeaaad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -40,6 +40,7 @@
import android.view.View;
import android.widget.TextView;
+import com.android.settingslib.Utils;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.FontSizeUtils;
@@ -84,6 +85,17 @@
private boolean mShowSeconds;
private Handler mSecondsHandler;
+ /**
+ * Whether we should use colors that adapt based on wallpaper/the scrim behind quick settings
+ * for text.
+ */
+ private boolean mUseWallpaperTextColor;
+
+ /**
+ * Color to be set on this {@link TextView}, when wallpaperTextColor is <b>not</b> utilized.
+ */
+ private int mNonAdaptedColor;
+
public Clock(Context context) {
this(context, null);
}
@@ -101,6 +113,7 @@
try {
mAmPmStyle = a.getInt(R.styleable.Clock_amPmStyle, AM_PM_STYLE_GONE);
mShowDark = a.getBoolean(R.styleable.Clock_showDark, true);
+ mNonAdaptedColor = getCurrentTextColor();
} finally {
a.recycle();
}
@@ -227,7 +240,10 @@
@Override
public void onDarkChanged(Rect area, float darkIntensity, int tint) {
- setTextColor(DarkIconDispatcher.getTint(area, this, tint));
+ mNonAdaptedColor = DarkIconDispatcher.getTint(area, this, tint);
+ if (!mUseWallpaperTextColor) {
+ setTextColor(mNonAdaptedColor);
+ }
}
@Override
@@ -242,6 +258,25 @@
0);
}
+ /**
+ * Sets whether the clock uses the wallpaperTextColor. If we're not using it, we'll revert back
+ * to dark-mode-based/tinted colors.
+ *
+ * @param shouldUseWallpaperTextColor whether we should use wallpaperTextColor for text color
+ */
+ public void useWallpaperTextColor(boolean shouldUseWallpaperTextColor) {
+ if (shouldUseWallpaperTextColor == mUseWallpaperTextColor) {
+ return;
+ }
+ mUseWallpaperTextColor = shouldUseWallpaperTextColor;
+
+ if (mUseWallpaperTextColor) {
+ setTextColor(Utils.getColorAttr(mContext, R.attr.wallpaperTextColor));
+ } else {
+ setTextColor(mNonAdaptedColor);
+ }
+ }
+
private void updateShowSeconds() {
if (mShowSeconds) {
// Wait until we have a display to start trying to show seconds.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index 74a30fa..ef630c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -27,6 +27,7 @@
import android.util.AttributeSet;
import android.widget.TextView;
+import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -42,6 +43,17 @@
private String mLastText;
private String mDatePattern;
+ /**
+ * Whether we should use colors that adapt based on wallpaper/the scrim behind quick settings
+ * for text.
+ */
+ private boolean mUseWallpaperTextColor;
+
+ /**
+ * Color to be set on this {@link TextView}, when wallpaperTextColor is <b>not</b> utilized.
+ */
+ private int mNonAdaptedTextColor;
+
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -62,6 +74,7 @@
public DateView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mNonAdaptedTextColor = getCurrentTextColor();
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.DateView,
@@ -117,6 +130,25 @@
}
}
+ /**
+ * Sets whether the date view uses the wallpaperTextColor. If we're not using it, we'll revert
+ * back to dark-mode-based/tinted colors.
+ *
+ * @param shouldUseWallpaperTextColor whether we should use wallpaperTextColor for text color
+ */
+ public void useWallpaperTextColor(boolean shouldUseWallpaperTextColor) {
+ if (shouldUseWallpaperTextColor == mUseWallpaperTextColor) {
+ return;
+ }
+ mUseWallpaperTextColor = shouldUseWallpaperTextColor;
+
+ if (mUseWallpaperTextColor) {
+ setTextColor(Utils.getColorAttr(mContext, R.attr.wallpaperTextColor));
+ } else {
+ setTextColor(mNonAdaptedTextColor);
+ }
+ }
+
public void setDatePattern(String pattern) {
if (TextUtils.equals(pattern, mDatePattern)) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 8f6fa49..375e860 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -70,6 +70,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.Utils;
+import com.android.systemui.Dependency;
import com.android.systemui.ExpandHelper;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -83,6 +84,7 @@
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.FooterView;
+import com.android.systemui.statusbar.NotificationBlockingHelperManager;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.NotificationGuts;
import com.android.systemui.statusbar.NotificationListContainer;
@@ -448,6 +450,13 @@
mRoundnessManager.setOnRoundingChangedCallback(this::invalidate);
addOnExpandedHeightListener(mRoundnessManager::setExpanded);
+ // Blocking helper manager wants to know the expanded state, update as well.
+ NotificationBlockingHelperManager blockingHelperManager =
+ Dependency.get(NotificationBlockingHelperManager.class);
+ addOnExpandedHeightListener((height, unused) -> {
+ blockingHelperManager.setNotificationShadeExpanded(height);
+ });
+
updateWillNotDraw();
mBackgroundPaint.setAntiAlias(true);
if (DEBUG) {
@@ -1038,45 +1047,63 @@
mQsContainer = qsContainer;
}
+ /**
+ * Handles cleanup after the given {@code view} has been fully swiped out (including
+ * re-invoking dismiss logic in case the notification has not made its way out yet).
+ */
@Override
- public void onChildDismissed(View v) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+ public void onChildDismissed(View view) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) view;
if (!row.isDismissed()) {
- handleChildDismissed(v);
+ handleChildViewDismissed(view);
}
ViewGroup transientContainer = row.getTransientContainer();
if (transientContainer != null) {
- transientContainer.removeTransientView(v);
+ transientContainer.removeTransientView(view);
}
}
- private void handleChildDismissed(View v) {
+ /**
+ * Starts up notification dismiss and tells the notification, if any, to remove itself from
+ * layout.
+ *
+ * @param view view (e.g. notification) to dismiss from the layout
+ */
+ private void handleChildViewDismissed(View view) {
if (mDismissAllInProgress) {
return;
}
+
+ boolean isBlockingHelperShown = false;
+
setSwipingInProgress(false);
- if (mDragAnimPendingChildren.contains(v)) {
- // We start the swipe and finish it in the same frame, we don't want any animation
- // for the drag
- mDragAnimPendingChildren.remove(v);
+ if (mDragAnimPendingChildren.contains(view)) {
+ // We start the swipe and finish it in the same frame; we don't want a drag animation.
+ mDragAnimPendingChildren.remove(view);
}
- mSwipedOutViews.add(v);
- mAmbientState.onDragFinished(v);
+ mAmbientState.onDragFinished(view);
updateContinuousShadowDrawing();
- if (v instanceof ExpandableNotificationRow) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+
+ if (view instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) view;
if (row.isHeadsUp()) {
mHeadsUpManager.addSwipedOutNotification(row.getStatusBarNotification().getKey());
}
- }
- if (v instanceof ExpandableNotificationRow) {
- ((ExpandableNotificationRow) v).performDismiss(false /* fromAccessibility */);
+ isBlockingHelperShown =
+ row.performDismissWithBlockingHelper(false /* fromAccessibility */);
}
+ if (!isBlockingHelperShown) {
+ mSwipedOutViews.add(view);
+ }
mFalsingManager.onNotificationDismissed();
if (mFalsingManager.shouldEnforceBouncer()) {
- mStatusBar.executeRunnableDismissingKeyguard(null, null /* cancelAction */,
- false /* dismissShade */, true /* afterKeyguardGone */, false /* deferred */);
+ mStatusBar.executeRunnableDismissingKeyguard(
+ null,
+ null /* cancelAction */,
+ false /* dismissShade */,
+ true /* afterKeyguardGone */,
+ false /* deferred */);
}
}
@@ -2729,9 +2756,8 @@
updateScrollStateForRemovedChild(expandableView);
boolean animationGenerated = generateRemoveAnimation(child);
if (animationGenerated) {
- if (!mSwipedOutViews.contains(child)) {
- container.getOverlay().add(child);
- } else if (Math.abs(expandableView.getTranslation()) != expandableView.getWidth()) {
+ if (!mSwipedOutViews.contains(child)
+ || Math.abs(expandableView.getTranslation()) != expandableView.getWidth()) {
container.addTransientView(child, 0);
expandableView.setTransientContainer(container);
}
@@ -4618,7 +4644,7 @@
if (mIsExpanded) {
// We don't want to quick-dismiss when it's a heads up as this might lead to closing
// of the panel early.
- handleChildDismissed(view);
+ handleChildViewDismissed(view);
}
mStatusBar.getGutsManager().closeAndSaveGuts(true /* removeLeavebehind */,
false /* force */, false /* removeControls */, -1 /* x */, -1 /* y */,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index d48ae76..c80bdc6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -51,6 +51,7 @@
= (int) (ANIMATION_DURATION_HEADS_UP_APPEAR
* HeadsUpAppearInterpolator.getFractionUntilOvershoot());
public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 300;
+ public static final int ANIMATION_DURATION_BLOCKING_HELPER_FADE = 240;
public static final int ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING = 80;
public static final int ANIMATION_DELAY_PER_ELEMENT_MANUAL = 32;
public static final int ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE = 48;
@@ -79,6 +80,7 @@
private ValueAnimator mBottomOverScrollAnimator;
private int mHeadsUpAppearHeightBottom;
private boolean mShadeExpanded;
+ private ArrayList<ExpandableView> mTransientViewsToRemove = new ArrayList<>();
private NotificationShelf mShelf;
private float mStatusBarIconLocation;
private int[] mTmpLocation = new int[2];
@@ -333,6 +335,12 @@
private void onAnimationFinished() {
mHostLayout.onChildAnimationFinished();
+
+ for (ExpandableView transientViewsToRemove : mTransientViewsToRemove) {
+ transientViewsToRemove.getTransientContainer()
+ .removeTransientView(transientViewsToRemove);
+ }
+ mTransientViewsToRemove.clear();
}
/**
@@ -362,7 +370,7 @@
} else if (event.animationType ==
NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE) {
if (changingView.getVisibility() != View.VISIBLE) {
- removeFromOverlay(changingView);
+ removeTransientView(changingView);
continue;
}
@@ -402,8 +410,7 @@
0, new Runnable() {
@Override
public void run() {
- // remove the temporary overlay
- removeFromOverlay(changingView);
+ removeTransientView(changingView);
}
}, null);
} else if (event.animationType ==
@@ -494,6 +501,12 @@
}
}
+ private static void removeTransientView(ExpandableView viewToRemove) {
+ if (viewToRemove.getTransientContainer() != null) {
+ viewToRemove.getTransientContainer().removeTransientView(viewToRemove);
+ }
+ }
+
public static void removeFromOverlay(View changingView) {
ViewGroup parent = (ViewGroup) changingView.getParent();
if (parent != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index fc932c3..1cbdfe8 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -37,6 +37,7 @@
public static String STORAGE = "DSK";
public static String TVPIP = "TPP";
public static String BATTERY = "BAT";
+ public static String HINTS = "HNT";
@VisibleForTesting
static void createAll(Context context) {
@@ -73,6 +74,12 @@
: NotificationManager.IMPORTANCE_LOW);
storage.setBypassDnd(true);
+ final NotificationChannel hint = new NotificationChannel(
+ HINTS,
+ context.getString(R.string.notification_channel_hints),
+ NotificationManager.IMPORTANCE_DEFAULT);
+ // No need to bypass DND.
+
nm.createNotificationChannels(Arrays.asList(
alerts,
general,
@@ -80,7 +87,8 @@
createScreenshotChannel(
context.getString(R.string.notification_channel_screenshot),
nm.getNotificationChannel(SCREENSHOTS_LEGACY)),
- batteryChannel
+ batteryChannel,
+ hint
));
// Delete older SS channel if present.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
index af29ab4..23a3405 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -40,8 +42,13 @@
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import java.util.function.Consumer;
@@ -49,52 +56,59 @@
@RunWith(AndroidJUnit4.class)
public class ExpandableNotificationRowTest extends SysuiTestCase {
- private ExpandableNotificationRow mGroup;
+ private ExpandableNotificationRow mGroupRow;
+
private NotificationTestHelper mNotificationTestHelper;
boolean mHeadsUpAnimatingAway = false;
+ @Rule public MockitoRule mockito = MockitoJUnit.rule();
+ @Mock private NotificationBlockingHelperManager mBlockingHelperManager;
+
@Before
public void setUp() throws Exception {
mNotificationTestHelper = new NotificationTestHelper(mContext);
- mGroup = mNotificationTestHelper.createGroup();
- mGroup.setHeadsUpAnimatingAwayListener(
+ mGroupRow = mNotificationTestHelper.createGroup();
+ mGroupRow.setHeadsUpAnimatingAwayListener(
animatingAway -> mHeadsUpAnimatingAway = animatingAway);
+ mDependency.injectTestDependency(
+ NotificationBlockingHelperManager.class,
+ mBlockingHelperManager);
}
@Test
public void testGroupSummaryNotShowingIconWhenPublic() {
- mGroup.setSensitive(true, true);
- mGroup.setHideSensitiveForIntrinsicHeight(true);
- Assert.assertTrue(mGroup.isSummaryWithChildren());
- Assert.assertFalse(mGroup.isShowingIcon());
+ mGroupRow.setSensitive(true, true);
+ mGroupRow.setHideSensitiveForIntrinsicHeight(true);
+ assertTrue(mGroupRow.isSummaryWithChildren());
+ assertFalse(mGroupRow.isShowingIcon());
}
@Test
public void testNotificationHeaderVisibleWhenAnimating() {
- mGroup.setSensitive(true, true);
- mGroup.setHideSensitive(true, false, 0, 0);
- mGroup.setHideSensitive(false, true, 0, 0);
- Assert.assertTrue(mGroup.getChildrenContainer().getVisibleHeader().getVisibility()
+ mGroupRow.setSensitive(true, true);
+ mGroupRow.setHideSensitive(true, false, 0, 0);
+ mGroupRow.setHideSensitive(false, true, 0, 0);
+ assertTrue(mGroupRow.getChildrenContainer().getVisibleHeader().getVisibility()
== View.VISIBLE);
}
@Test
public void testUserLockedResetEvenWhenNoChildren() {
- mGroup.setUserLocked(true);
- mGroup.removeAllChildren();
- mGroup.setUserLocked(false);
- Assert.assertFalse("The childrencontainer should not be userlocked but is, the state "
- + "seems out of sync.", mGroup.getChildrenContainer().isUserLocked());
+ mGroupRow.setUserLocked(true);
+ mGroupRow.removeAllChildren();
+ mGroupRow.setUserLocked(false);
+ assertFalse("The childrencontainer should not be userlocked but is, the state "
+ + "seems out of sync.", mGroupRow.getChildrenContainer().isUserLocked());
}
@Test
public void testReinflatedOnDensityChange() {
- mGroup.setUserLocked(true);
- mGroup.removeAllChildren();
- mGroup.setUserLocked(false);
+ mGroupRow.setUserLocked(true);
+ mGroupRow.removeAllChildren();
+ mGroupRow.setUserLocked(false);
NotificationChildrenContainer mockContainer = mock(NotificationChildrenContainer.class);
- mGroup.setChildrenContainer(mockContainer);
- mGroup.onDensityOrFontScaleChanged();
+ mGroupRow.setChildrenContainer(mockContainer);
+ mGroupRow.onDensityOrFontScaleChanged();
verify(mockContainer).reInflateViews(any(), any());
}
@@ -151,38 +165,38 @@
@Test
public void testClickSound() throws Exception {
- Assert.assertTrue("Should play sounds by default.", mGroup.isSoundEffectsEnabled());
- mGroup.setDark(true /* dark */, false /* fade */, 0 /* delay */);
- mGroup.setSecureStateProvider(()-> false);
- Assert.assertFalse("Shouldn't play sounds when dark and trusted.",
- mGroup.isSoundEffectsEnabled());
- mGroup.setSecureStateProvider(()-> true);
- Assert.assertTrue("Should always play sounds when not trusted.",
- mGroup.isSoundEffectsEnabled());
+ assertTrue("Should play sounds by default.", mGroupRow.isSoundEffectsEnabled());
+ mGroupRow.setDark(true /* dark */, false /* fade */, 0 /* delay */);
+ mGroupRow.setSecureStateProvider(()-> false);
+ assertFalse("Shouldn't play sounds when dark and trusted.",
+ mGroupRow.isSoundEffectsEnabled());
+ mGroupRow.setSecureStateProvider(()-> true);
+ assertTrue("Should always play sounds when not trusted.",
+ mGroupRow.isSoundEffectsEnabled());
}
@Test
public void testSetDismissed_longPressListenerRemoved() {
ExpandableNotificationRow.LongPressListener listener =
mock(ExpandableNotificationRow.LongPressListener.class);
- mGroup.setLongPressListener(listener);
- mGroup.doLongClickCallback(0,0);
- verify(listener, times(1)).onLongPress(eq(mGroup), eq(0), eq(0),
+ mGroupRow.setLongPressListener(listener);
+ mGroupRow.doLongClickCallback(0,0);
+ verify(listener, times(1)).onLongPress(eq(mGroupRow), eq(0), eq(0),
any(NotificationMenuRowPlugin.MenuItem.class));
reset(listener);
- mGroup.setDismissed(true);
- mGroup.doLongClickCallback(0,0);
- verify(listener, times(0)).onLongPress(eq(mGroup), eq(0), eq(0),
+ mGroupRow.setDismissed(true);
+ mGroupRow.doLongClickCallback(0,0);
+ verify(listener, times(0)).onLongPress(eq(mGroupRow), eq(0), eq(0),
any(NotificationMenuRowPlugin.MenuItem.class));
}
@Test
public void testShowAppOps_noHeader() {
// public notification is custom layout - no header
- mGroup.setSensitive(true, true);
- mGroup.setAppOpsOnClickListener(null);
- mGroup.showAppOpsIcons(null);
+ mGroupRow.setSensitive(true, true);
+ mGroupRow.setAppOpsOnClickListener(null);
+ mGroupRow.showAppOpsIcons(null);
}
@Test
@@ -190,17 +204,17 @@
NotificationHeaderView mockHeader = mock(NotificationHeaderView.class);
NotificationContentView publicLayout = mock(NotificationContentView.class);
- mGroup.setPublicLayout(publicLayout);
+ mGroupRow.setPublicLayout(publicLayout);
NotificationContentView privateLayout = mock(NotificationContentView.class);
- mGroup.setPrivateLayout(privateLayout);
+ mGroupRow.setPrivateLayout(privateLayout);
NotificationChildrenContainer mockContainer = mock(NotificationChildrenContainer.class);
when(mockContainer.getNotificationChildCount()).thenReturn(1);
when(mockContainer.getHeaderView()).thenReturn(mockHeader);
- mGroup.setChildrenContainer(mockContainer);
+ mGroupRow.setChildrenContainer(mockContainer);
ArraySet<Integer> ops = new ArraySet<>();
ops.add(AppOpsManager.OP_ANSWER_PHONE_CALLS);
- mGroup.showAppOpsIcons(ops);
+ mGroupRow.showAppOpsIcons(ops);
verify(mockHeader, times(1)).showAppOpsIcons(ops);
verify(privateLayout, times(1)).showAppOpsIcons(ops);
@@ -214,17 +228,50 @@
ExpandableNotificationRow.OnAppOpsClickListener.class);
View view = mock(View.class);
- mGroup.setAppOpsOnClickListener(l);
+ mGroupRow.setAppOpsOnClickListener(l);
- mGroup.getAppOpsOnClickListener().onClick(view);
+ mGroupRow.getAppOpsOnClickListener().onClick(view);
verify(l, times(1)).onClick(any(), anyInt(), anyInt(), any());
}
@Test
public void testHeadsUpAnimatingAwayListener() {
- mGroup.setHeadsUpAnimatingAway(true);
+ mGroupRow.setHeadsUpAnimatingAway(true);
Assert.assertEquals(true, mHeadsUpAnimatingAway);
- mGroup.setHeadsUpAnimatingAway(false);
+ mGroupRow.setHeadsUpAnimatingAway(false);
Assert.assertEquals(false, mHeadsUpAnimatingAway);
}
+
+ @Test
+ public void testPerformDismissWithBlockingHelper_falseWhenBlockingHelperIsntShown() {
+ when(mBlockingHelperManager.perhapsShowBlockingHelper(
+ eq(mGroupRow), any(NotificationMenuRowPlugin.class))).thenReturn(false);
+
+ assertFalse(
+ mGroupRow.performDismissWithBlockingHelper(false /* fromAccessibility */));
+ }
+
+ @Test
+ public void testPerformDismissWithBlockingHelper_doesntPerformOnGroupSummary() {
+ ExpandableNotificationRow childRow = mGroupRow.getChildrenContainer().getViewAtPosition(0);
+ when(mBlockingHelperManager.perhapsShowBlockingHelper(eq(childRow), any(NotificationMenuRowPlugin.class)))
+ .thenReturn(true);
+
+ assertTrue(
+ childRow.performDismissWithBlockingHelper(false /* fromAccessibility */));
+
+ verify(mBlockingHelperManager, times(1))
+ .perhapsShowBlockingHelper(eq(childRow), any(NotificationMenuRowPlugin.class));
+ verify(mBlockingHelperManager, times(0))
+ .perhapsShowBlockingHelper(eq(mGroupRow), any(NotificationMenuRowPlugin.class));
+ }
+
+ @Test
+ public void testIsBlockingHelperShowing_isCorrectlyUpdated() {
+ mGroupRow.setBlockingHelperShowing(true);
+ assertTrue(mGroupRow.isBlockingHelperShowing());
+
+ mGroupRow.setBlockingHelperShowing(false);
+ assertFalse(mGroupRow.isBlockingHelperShowing());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationBlockingHelperManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationBlockingHelperManagerTest.java
new file mode 100644
index 0000000..64f34e0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationBlockingHelperManagerTest.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+
+import android.content.Context;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.View;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
+import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
+import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for {@link NotificationBlockingHelperManager}.
+ */
+@SmallTest
+@org.junit.runner.RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class NotificationBlockingHelperManagerTest extends SysuiTestCase {
+
+ private NotificationBlockingHelperManager mBlockingHelperManager;
+
+ private NotificationTestHelper mHelper;
+
+ @Rule public MockitoRule mockito = MockitoJUnit.rule();
+ @Mock private NotificationGutsManager mGutsManager;
+ @Mock private NotificationEntryManager mEntryManager;
+ @Mock private NotificationMenuRow mMenuRow;
+ @Mock private NotificationMenuRowPlugin.MenuItem mMenuItem;
+
+ @Before
+ public void setUp() {
+ mBlockingHelperManager = new NotificationBlockingHelperManager(mContext);
+
+ mHelper = new NotificationTestHelper(mContext);
+ when(mGutsManager.openGuts(
+ any(View.class),
+ anyInt(),
+ anyInt(),
+ any(NotificationMenuRowPlugin.MenuItem.class)))
+ .thenReturn(true);
+ mDependency.injectTestDependency(NotificationGutsManager.class, mGutsManager);
+ mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
+ when(mMenuRow.getLongpressMenuItem(any(Context.class))).thenReturn(mMenuItem);
+ }
+
+ @Test
+ public void testDismissCurrentBlockingHelper_nullBlockingHelperRow() {
+ // By default, this shouldn't dismiss (no pointers/vars set up!)
+ assertFalse(mBlockingHelperManager.dismissCurrentBlockingHelper());
+ assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
+ }
+
+ @Test
+ public void testDismissCurrentBlockingHelper_withDetachedBlockingHelperRow() throws Exception {
+ ExpandableNotificationRow row = spy(mHelper.createRow());
+ row.setBlockingHelperShowing(true);
+ when(row.isAttachedToWindow()).thenReturn(false);
+ mBlockingHelperManager.setBlockingHelperRowForTest(row);
+
+ assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
+ assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
+
+ verify(mEntryManager, times(0)).updateNotifications();
+ }
+
+ @Test
+ public void testDismissCurrentBlockingHelper_withAttachedBlockingHelperRow() throws Exception {
+ ExpandableNotificationRow row = spy(mHelper.createRow());
+ row.setBlockingHelperShowing(true);
+ when(row.isAttachedToWindow()).thenReturn(true);
+ mBlockingHelperManager.setBlockingHelperRowForTest(row);
+
+ assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
+ assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
+
+ verify(mEntryManager).updateNotifications();
+ }
+
+ @Test
+ public void testPerhapsShowBlockingHelper_shown() throws Exception {
+ ExpandableNotificationRow row = mHelper.createRow();
+ row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+ mBlockingHelperManager.setNotificationShadeExpanded(1f);
+
+ assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
+
+ verify(mGutsManager).openGuts(row, 0, 0, mMenuItem);
+ }
+
+
+ @Test
+ public void testPerhapsShowBlockingHelper_shownForLargeGroup() throws Exception {
+ ExpandableNotificationRow groupRow = mHelper.createGroup(10);
+ groupRow.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+ mBlockingHelperManager.setNotificationShadeExpanded(1f);
+
+ assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(groupRow, mMenuRow));
+
+ verify(mGutsManager).openGuts(groupRow, 0, 0, mMenuItem);
+ }
+
+ @Test
+ public void testPerhapsShowBlockingHelper_shownForOnlyChildNotification()
+ throws Exception {
+ ExpandableNotificationRow groupRow = mHelper.createGroup(1);
+ // Explicitly get the children container & call getViewAtPosition on it instead of the row
+ // as other factors such as view expansion may cause us to get the parent row back instead
+ // of the child row.
+ ExpandableNotificationRow childRow = groupRow.getChildrenContainer().getViewAtPosition(0);
+ childRow.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+ mBlockingHelperManager.setNotificationShadeExpanded(1f);
+
+ assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(childRow, mMenuRow));
+
+ verify(mGutsManager).openGuts(childRow, 0, 0, mMenuItem);
+ }
+
+ @Test
+ public void testPerhapsShowBlockingHelper_notShownDueToNeutralUserSentiment() throws Exception {
+ ExpandableNotificationRow row = mHelper.createRow();
+ row.getEntry().userSentiment = USER_SENTIMENT_NEUTRAL;
+ mBlockingHelperManager.setNotificationShadeExpanded(1f);
+
+ assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
+ }
+
+ @Test
+ public void testPerhapsShowBlockingHelper_notShownDueToPositiveUserSentiment()
+ throws Exception {
+ ExpandableNotificationRow row = mHelper.createRow();
+ row.getEntry().userSentiment = USER_SENTIMENT_POSITIVE;
+ mBlockingHelperManager.setNotificationShadeExpanded(1f);
+
+ assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
+ }
+
+ @Test
+ public void testPerhapsShowBlockingHelper_notShownDueToShadeVisibility() throws Exception {
+ ExpandableNotificationRow row = mHelper.createRow();
+ row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+ // Hide the shade
+ mBlockingHelperManager.setNotificationShadeExpanded(0f);
+
+ assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
+ }
+
+ @Test
+ public void testPerhapsShowBlockingHelper_notShownAsNotificationIsInMultipleChildGroup()
+ throws Exception {
+ ExpandableNotificationRow groupRow = mHelper.createGroup(2);
+ // Explicitly get the children container & call getViewAtPosition on it instead of the row
+ // as other factors such as view expansion may cause us to get the parent row back instead
+ // of the child row.
+ ExpandableNotificationRow childRow = groupRow.getChildrenContainer().getViewAtPosition(0);
+ childRow.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+ mBlockingHelperManager.setNotificationShadeExpanded(1f);
+
+ assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(childRow, mMenuRow));
+ }
+
+ @Test
+ public void testBlockingHelperShowAndDismiss() throws Exception{
+ ExpandableNotificationRow row = spy(mHelper.createRow());
+ row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+ when(row.isAttachedToWindow()).thenReturn(true);
+ mBlockingHelperManager.setNotificationShadeExpanded(1f);
+
+ // Show check
+ assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
+
+ verify(mGutsManager).openGuts(row, 0, 0, mMenuItem);
+
+ // Dismiss check
+ assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
+ assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
+
+ verify(mEntryManager).updateNotifications();
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsManagerTest.java
index 6209d59..21f6750 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsManagerTest.java
@@ -20,6 +20,7 @@
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
+import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
import static junit.framework.Assert.assertNotNull;
import static org.junit.Assert.assertEquals;
@@ -27,6 +28,8 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -34,31 +37,24 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.times;
+import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
-import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArraySet;
-import android.view.LayoutInflater;
import android.view.View;
-import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.NotificationGuts;
-import com.android.systemui.statusbar.NotificationTestHelper;
-import com.android.systemui.statusbar.notification.NotificationInflater;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import org.junit.Before;
@@ -70,15 +66,18 @@
import org.mockito.junit.MockitoRule;
import org.mockito.junit.MockitoJUnit;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Tests for {@link NotificationGutsManager}.
+ */
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class NotificationGutsManagerTest extends SysuiTestCase {
private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
- private final String mPackageName = mContext.getPackageName();
- private final int mUid = Binder.getCallingUid();
-
private NotificationChannel mTestNotificationChannel = new NotificationChannel(
TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
private TestableLooper mTestableLooper;
@@ -87,7 +86,6 @@
private NotificationGutsManager mGutsManager;
@Rule public MockitoRule mockito = MockitoJUnit.rule();
- @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@Mock private NotificationPresenter mPresenter;
@Mock private NotificationEntryManager mEntryManager;
@Mock private NotificationStackScrollLayout mStackScroller;
@@ -118,7 +116,12 @@
});
// Test doesn't support animation since the guts view is not attached.
- doNothing().when(guts).openControls(anyInt(), anyInt(), anyBoolean(), any(Runnable.class));
+ doNothing().when(guts).openControls(
+ eq(true) /* shouldDoCircularReveal */,
+ anyInt(),
+ anyInt(),
+ anyBoolean(),
+ any(Runnable.class));
ExpandableNotificationRow realRow = createTestNotificationRow();
NotificationMenuRowPlugin.MenuItem menuItem = createTestMenuItem(realRow);
@@ -130,7 +133,12 @@
mGutsManager.openGuts(row, 0, 0, menuItem);
assertEquals(View.INVISIBLE, guts.getVisibility());
mTestableLooper.processAllMessages();
- verify(guts).openControls(anyInt(), anyInt(), anyBoolean(), any(Runnable.class));
+ verify(guts).openControls(
+ eq(true),
+ anyInt(),
+ anyInt(),
+ anyBoolean(),
+ any(Runnable.class));
assertEquals(View.VISIBLE, guts.getVisibility());
mGutsManager.closeAndSaveGuts(false, false, false, 0, 0, false);
@@ -148,7 +156,12 @@
});
// Test doesn't support animation since the guts view is not attached.
- doNothing().when(guts).openControls(anyInt(), anyInt(), anyBoolean(), any(Runnable.class));
+ doNothing().when(guts).openControls(
+ eq(true) /* shouldDoCircularReveal */,
+ anyInt(),
+ anyInt(),
+ anyBoolean(),
+ any(Runnable.class));
ExpandableNotificationRow realRow = createTestNotificationRow();
NotificationMenuRowPlugin.MenuItem menuItem = createTestMenuItem(realRow);
@@ -160,7 +173,12 @@
mGutsManager.openGuts(row, 0, 0, menuItem);
mTestableLooper.processAllMessages();
- verify(guts).openControls(anyInt(), anyInt(), anyBoolean(), any(Runnable.class));
+ verify(guts).openControls(
+ eq(true),
+ anyInt(),
+ anyInt(),
+ anyBoolean(),
+ any(Runnable.class));
row.onDensityOrFontScaleChanged();
mGutsManager.onDensityOrFontScaleChanged(row);
@@ -247,6 +265,56 @@
assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction());
}
+ @Test
+ public void testInitializeNotificationInfoView_showBlockingHelper() throws Exception {
+ NotificationInfo notificationInfoView = mock(NotificationInfo.class);
+ ExpandableNotificationRow row = mHelper.createRow();
+ row.setBlockingHelperShowing(true);
+ row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+ StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+
+ verify(notificationInfoView).bindNotification(
+ any(PackageManager.class),
+ any(INotificationManager.class),
+ eq(statusBarNotification.getPackageName()),
+ isNull(),
+ anyInt(),
+ eq(statusBarNotification),
+ any(NotificationInfo.CheckSaveListener.class),
+ any(NotificationInfo.OnSettingsClickListener.class),
+ any(NotificationInfo.OnAppSettingsClickListener.class),
+ any(),
+ eq(true) /* isForBlockingHelper */,
+ eq(true) /* isUserSentimentNegative */);
+ }
+
+ @Test
+ public void testInitializeNotificationInfoView_dontShowBlockingHelper() throws Exception {
+ NotificationInfo notificationInfoView = mock(NotificationInfo.class);
+ ExpandableNotificationRow row = mHelper.createRow();
+ row.setBlockingHelperShowing(false);
+ row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+ StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+
+ verify(notificationInfoView).bindNotification(
+ any(PackageManager.class),
+ any(INotificationManager.class),
+ eq(statusBarNotification.getPackageName()),
+ isNull(),
+ anyInt(),
+ eq(statusBarNotification),
+ any(NotificationInfo.CheckSaveListener.class),
+ any(NotificationInfo.OnSettingsClickListener.class),
+ any(NotificationInfo.OnAppSettingsClickListener.class),
+ any(),
+ eq(false) /* isForBlockingHelper */,
+ eq(true) /* isUserSentimentNegative */);
+ }
+
////////////////////////////////////////////////////////////////////////////////////////////////
// Utility methods:
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 01664b2..7dda8b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -67,9 +67,13 @@
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import java.util.ArrayList;
import java.util.Collections;
@@ -87,14 +91,21 @@
private static final String TEST_CHANNEL_NAME = "TEST CHANNEL NAME";
private NotificationInfo mNotificationInfo;
- private final INotificationManager mMockINotificationManager = mock(INotificationManager.class);
- private final PackageManager mMockPackageManager = mock(PackageManager.class);
private NotificationChannel mNotificationChannel;
private NotificationChannel mDefaultNotificationChannel;
private StatusBarNotification mSbn;
+ @Rule public MockitoRule mockito = MockitoJUnit.rule();
+ @Mock private INotificationManager mMockINotificationManager;
+ @Mock private PackageManager mMockPackageManager;
+ @Mock private NotificationBlockingHelperManager mBlockingHelperManager;
+
@Before
public void setUp() throws Exception {
+ mDependency.injectTestDependency(
+ NotificationBlockingHelperManager.class,
+ mBlockingHelperManager);
+
// Inflate the layout
final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
mNotificationInfo = (NotificationInfo) layoutInflater.inflate(R.layout.notification_info,
@@ -311,7 +322,7 @@
public void testbindNotification_BlockingHelper() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null,
- null, null, true);
+ null, null, false, true);
final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
assertEquals(View.VISIBLE, view.getVisibility());
assertEquals(mContext.getString(R.string.inline_blocking_helper), view.getText());
@@ -386,6 +397,27 @@
}
@Test
+ public void testCloseControls_blockingHelperDismissedIfShown() throws Exception {
+ mNotificationInfo.bindNotification(
+ mMockPackageManager,
+ mMockINotificationManager,
+ TEST_PACKAGE_NAME,
+ mNotificationChannel,
+ 1 /* numChannels */,
+ mSbn,
+ null /* checkSaveListener */,
+ null /* onSettingsClick */,
+ null /* onAppSettingsClick */,
+ null /* nonBlockablePkgs */,
+ true /* isForBlockingHelper */,
+ false /* isUserSentimentNegative */);
+
+ mNotificationInfo.closeControls(mNotificationInfo);
+
+ verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
+ }
+
+ @Test
public void testNonBlockableAppDoesNotBecomeBlocked() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index 2764254..de2e6bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.Instrumentation;
import android.app.Notification;
@@ -23,33 +24,32 @@
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.support.test.InstrumentationRegistry;
+import android.text.TextUtils;
import android.view.LayoutInflater;
-import android.widget.FrameLayout;
import android.widget.RemoteViews;
import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
-import com.android.systemui.statusbar.notification.AboveShelfObserver;
-import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationInflaterTest;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
/**
- * A helper class to create {@link ExpandableNotificationRow}
+ * A helper class to create {@link ExpandableNotificationRow} (for both individual and group
+ * notifications).
*/
public class NotificationTestHelper {
+ static final String PKG = "com.android.systemui";
+ static final int UID = 1000;
+ private static final String GROUP_KEY = "gruKey";
+
private final Context mContext;
private final Instrumentation mInstrumentation;
private int mId;
private final NotificationGroupManager mGroupManager = new NotificationGroupManager();
private ExpandableNotificationRow mRow;
- private InflationException mException;
private HeadsUpManager mHeadsUpManager;
- protected static final String PKG = "com.android.systemui";
- protected static final int UID = 1000;
public NotificationTestHelper(Context context) {
mContext = context;
@@ -57,57 +57,125 @@
mHeadsUpManager = new HeadsUpManagerPhone(mContext, null, mGroupManager, null, null);
}
+ public ExpandableNotificationRow createRow() throws Exception {
+ return createRow(PKG, UID);
+ }
+
public ExpandableNotificationRow createRow(String pkg, int uid) throws Exception {
+ return createRow(pkg, uid, false /* isGroupSummary */, null /* groupKey */);
+ }
+
+ public ExpandableNotificationRow createRow(Notification notification) throws Exception {
+ return generateRow(notification, PKG, UID, false /* isGroupRow */);
+ }
+
+ /**
+ * Returns an {@link ExpandableNotificationRow} group with the given number of child
+ * notifications.
+ */
+ public ExpandableNotificationRow createGroup(int numChildren) throws Exception {
+ ExpandableNotificationRow row = createGroupSummary(GROUP_KEY);
+ for (int i = 0; i < numChildren; i++) {
+ ExpandableNotificationRow childRow = createGroupChild(GROUP_KEY);
+ row.addChildNotification(childRow);
+ }
+ return row;
+ }
+
+ /** Returns a group notification with 2 child notifications. */
+ public ExpandableNotificationRow createGroup() throws Exception {
+ return createGroup(2);
+ }
+
+ private ExpandableNotificationRow createGroupSummary(String groupkey) throws Exception {
+ return createRow(PKG, UID, true /* isGroupSummary */, groupkey);
+ }
+
+ private ExpandableNotificationRow createGroupChild(String groupkey) throws Exception {
+ return createRow(PKG, UID, false /* isGroupSummary */, groupkey);
+ }
+
+ /**
+ * Creates a notification row with the given details.
+ *
+ * @param pkg package used for creating a {@link StatusBarNotification}
+ * @param uid uid used for creating a {@link StatusBarNotification}
+ * @param isGroupSummary whether the notification row is a group summary
+ * @param groupKey the group key for the notification group used across notifications
+ * @return a row with that's either a standalone notification or a group notification if the
+ * groupKey is non-null
+ * @throws Exception
+ */
+ private ExpandableNotificationRow createRow(
+ String pkg,
+ int uid,
+ boolean isGroupSummary,
+ @Nullable String groupKey)
+ throws Exception {
Notification publicVersion = new Notification.Builder(mContext).setSmallIcon(
R.drawable.ic_person)
.setCustomContentView(new RemoteViews(mContext.getPackageName(),
R.layout.custom_view_dark))
.build();
- Notification notification = new Notification.Builder(mContext).setSmallIcon(
- R.drawable.ic_person)
- .setContentTitle("Title")
- .setContentText("Text")
- .setPublicVersion(publicVersion)
- .build();
- return createRow(notification, pkg, uid);
+ Notification.Builder notificationBuilder =
+ new Notification.Builder(mContext)
+ .setSmallIcon(R.drawable.ic_person)
+ .setContentTitle("Title")
+ .setContentText("Text")
+ .setPublicVersion(publicVersion);
+
+ // Group notification setup
+ if (isGroupSummary) {
+ notificationBuilder.setGroupSummary(true);
+ }
+ if (!TextUtils.isEmpty(groupKey)) {
+ notificationBuilder.setGroup(groupKey);
+ }
+
+ return generateRow(notificationBuilder.build(), pkg, uid, !TextUtils.isEmpty(groupKey));
}
- public ExpandableNotificationRow createRow() throws Exception {
- return createRow(PKG, UID);
- }
-
- public ExpandableNotificationRow createRow(Notification notification) throws Exception {
- return createRow(notification, PKG, UID);
- }
-
- public ExpandableNotificationRow createRow(Notification notification, String pkg, int uid)
+ private ExpandableNotificationRow generateRow(
+ Notification notification,
+ String pkg,
+ int uid,
+ boolean isGroupRow)
throws Exception {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
mContext.LAYOUT_INFLATER_SERVICE);
- mInstrumentation.runOnMainSync(() -> {
- mRow = (ExpandableNotificationRow) inflater.inflate(
- R.layout.status_bar_notification_row,
- null, false);
- });
+ mInstrumentation.runOnMainSync(() ->
+ mRow = (ExpandableNotificationRow) inflater.inflate(
+ R.layout.status_bar_notification_row,
+ null /* root */,
+ false /* attachToRoot */)
+ );
ExpandableNotificationRow row = mRow;
row.setGroupManager(mGroupManager);
row.setHeadsUpManager(mHeadsUpManager);
row.setAboveShelfChangedListener(aboveShelf -> {});
UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
- StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, mId++, null, uid,
- 2000, notification, mUser, null, System.currentTimeMillis());
+ StatusBarNotification sbn = new StatusBarNotification(
+ pkg,
+ pkg,
+ mId++,
+ null /* tag */,
+ uid,
+ 2000 /* initialPid */,
+ notification,
+ mUser,
+ null /* overrideGroupKey */,
+ System.currentTimeMillis());
NotificationData.Entry entry = new NotificationData.Entry(sbn);
entry.row = row;
entry.createIcons(mContext, sbn);
- NotificationInflaterTest.runThenWaitForInflation(() -> row.updateNotification(entry),
+ NotificationInflaterTest.runThenWaitForInflation(
+ () -> row.updateNotification(entry),
row.getNotificationInflater());
- return row;
- }
- public ExpandableNotificationRow createGroup() throws Exception {
- ExpandableNotificationRow row = createRow();
- row.addChildNotification(createRow());
- row.addChildNotification(createRow());
+ // This would be done as part of onAsyncInflationFinished, but we skip large amounts of
+ // the callback chain, so we need to make up for not adding it to the group manager
+ // here.
+ mGroupManager.onEntryAdded(entry);
return row;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 7743c6b..a88f31a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -26,6 +26,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
@@ -73,7 +74,7 @@
@Before
public void setup() {
mLightBarController = mock(LightBarController.class);
- mScrimBehind = new ScrimView(getContext());
+ mScrimBehind = spy(new ScrimView(getContext()));
mScrimInFront = new ScrimView(getContext());
mWakeLock = mock(WakeLock.class);
mAlarmManager = mock(AlarmManager.class);
@@ -210,8 +211,10 @@
mScrimController.finishAnimationsImmediately();
final float scrimAlpha = mScrimBehind.getViewAlpha();
+ reset(mScrimBehind);
mScrimController.setExpansionAffectsAlpha(false);
mScrimController.setPanelExpansion(0.8f);
+ verifyZeroInteractions(mScrimBehind);
Assert.assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha "
+ "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index f81ffd8..4a66bb7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -70,6 +70,7 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.assist.AssistManager;
+import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.statusbar.ActivatableNotificationView;
@@ -132,6 +133,7 @@
@Mock private NotificationViewHierarchyManager mViewHierarchyManager;
@Mock private VisualStabilityManager mVisualStabilityManager;
@Mock private NotificationListener mNotificationListener;
+ @Mock private KeyguardViewMediator mKeyguardViewMediator;
private TestableStatusBar mStatusBar;
private FakeMetricsLogger mMetricsLogger;
@@ -200,7 +202,7 @@
mPowerManager, mNotificationPanelView, mBarService, mNotificationListener,
mNotificationLogger, mVisualStabilityManager, mViewHierarchyManager,
mEntryManager, mScrimController, mFingerprintUnlockController,
- mock(ActivityLaunchAnimator.class));
+ mock(ActivityLaunchAnimator.class), mKeyguardViewMediator);
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mContext.getComponents();
mEntryManager.setUpForTest(mStatusBar, mStackScroller, mStatusBar, mHeadsUpManager,
@@ -638,7 +640,7 @@
NotificationViewHierarchyManager viewHierarchyManager,
TestableNotificationEntryManager entryManager, ScrimController scrimController,
FingerprintUnlockController fingerprintUnlockController,
- ActivityLaunchAnimator launchAnimator) {
+ ActivityLaunchAnimator launchAnimator, KeyguardViewMediator keyguardViewMediator) {
mStatusBarKeyguardViewManager = man;
mUnlockMethodCache = unlock;
mKeyguardIndicationController = key;
@@ -656,6 +658,7 @@
mScrimController = scrimController;
mFingerprintUnlockController = fingerprintUnlockController;
mActivityLaunchAnimator = launchAnimator;
+ mKeyguardViewMediator = keyguardViewMediator;
mClearAllEnabled = true;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
index 42069e2..cd3031b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
@@ -16,7 +16,12 @@
package com.android.systemui.statusbar.stack;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -25,33 +30,73 @@
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
+import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.TestableDependency;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.FooterView;
+import com.android.systemui.statusbar.NotificationBlockingHelperManager;
+import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBar;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+/**
+ * Tests for {@link NotificationStackScrollLayout}.
+ */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class NotificationStackScrollLayoutTest extends SysuiTestCase {
private NotificationStackScrollLayout mStackScroller;
- private StatusBar mBar;
+
+ @Rule public MockitoRule mockito = MockitoJUnit.rule();
+ @Mock private StatusBar mBar;
+ @Mock private HeadsUpManagerPhone mHeadsUpManager;
+ @Mock private NotificationBlockingHelperManager mBlockingHelperManager;
+ @Mock private NotificationGroupManager mGroupManager;
+ @Mock private ExpandHelper mExpandHelper;
+ @Mock private EmptyShadeView mEmptyShadeView;
@Before
@UiThreadTest
public void setUp() throws Exception {
+ // Inject dependencies before initializing the layout
+ mDependency.injectTestDependency(
+ NotificationBlockingHelperManager.class,
+ mBlockingHelperManager);
+
+ NotificationShelf notificationShelf = spy(new NotificationShelf(getContext(), null));
mStackScroller = new NotificationStackScrollLayout(getContext());
- mBar = mock(StatusBar.class);
+ mStackScroller.setShelf(notificationShelf);
mStackScroller.setStatusBar(mBar);
mStackScroller.setScrimController(mock(ScrimController.class));
+ mStackScroller.setHeadsUpManager(mHeadsUpManager);
+ mStackScroller.setGroupManager(mGroupManager);
+ mStackScroller.setEmptyShadeView(mEmptyShadeView);
+
+ // Stub out functionality that isn't necessary to test.
+ doNothing().when(mBar)
+ .executeRunnableDismissingKeyguard(any(Runnable.class),
+ any(Runnable.class),
+ anyBoolean(),
+ anyBoolean(),
+ anyBoolean());
+ doNothing().when(mGroupManager).collapseAllGroups();
+ doNothing().when(mExpandHelper).cancelImmediately();
+ doNothing().when(notificationShelf).setAnimationsEnabled(anyBoolean());
}
@Test
@@ -75,26 +120,34 @@
@Test
public void updateEmptyView_dndSuppressing() {
- EmptyShadeView view = mock(EmptyShadeView.class);
- mStackScroller.setEmptyShadeView(view);
- when(view.willBeGone()).thenReturn(true);
+ when(mEmptyShadeView.willBeGone()).thenReturn(true);
when(mBar.areNotificationsHidden()).thenReturn(true);
mStackScroller.updateEmptyShadeView(true);
- verify(view).setText(R.string.dnd_suppressing_shade_text);
+ verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
}
@Test
public void updateEmptyView_dndNotSuppressing() {
- EmptyShadeView view = mock(EmptyShadeView.class);
- mStackScroller.setEmptyShadeView(view);
- when(view.willBeGone()).thenReturn(true);
+ mStackScroller.setEmptyShadeView(mEmptyShadeView);
+ when(mEmptyShadeView.willBeGone()).thenReturn(true);
when(mBar.areNotificationsHidden()).thenReturn(false);
mStackScroller.updateEmptyShadeView(true);
- verify(view).setText(R.string.empty_shade_text);
+ verify(mEmptyShadeView).setText(R.string.empty_shade_text);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSetExpandedHeight_blockingHelperManagerReceivedCallbacks() {
+ mStackScroller.setExpandedHeight(0f);
+ verify(mBlockingHelperManager).setNotificationShadeExpanded(0f);
+ reset(mBlockingHelperManager);
+
+ mStackScroller.setExpandedHeight(100f);
+ verify(mBlockingHelperManager).setNotificationShadeExpanded(100f);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java
index 80dc2c9..50b4f3f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java
@@ -60,7 +60,8 @@
NotificationChannels.SCREENSHOTS_HEADSUP,
NotificationChannels.STORAGE,
NotificationChannels.GENERAL,
- NotificationChannels.BATTERY
+ NotificationChannels.BATTERY,
+ NotificationChannels.HINTS
));
NotificationChannels.createAll(mContext);
ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-land/config.xml
new file mode 100644
index 0000000..1aa1af3
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-land/config.xml
@@ -0,0 +1,21 @@
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<resources>
+ <dimen name="quick_qs_offset_height">@dimen/status_bar_height_landscape</dimen>
+ <!-- Total height of QQS in landscape, this is effectively status_bar_height_landscape + 128 -->
+ <dimen name="quick_qs_total_height">156dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-land/config.xml
new file mode 100644
index 0000000..1aa1af3
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-land/config.xml
@@ -0,0 +1,21 @@
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<resources>
+ <dimen name="quick_qs_offset_height">@dimen/status_bar_height_landscape</dimen>
+ <!-- Total height of QQS in landscape, this is effectively status_bar_height_landscape + 128 -->
+ <dimen name="quick_qs_total_height">156dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-land/config.xml
new file mode 100644
index 0000000..1aa1af3
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-land/config.xml
@@ -0,0 +1,21 @@
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<resources>
+ <dimen name="quick_qs_offset_height">@dimen/status_bar_height_landscape</dimen>
+ <!-- Total height of QQS in landscape, this is effectively status_bar_height_landscape + 128 -->
+ <dimen name="quick_qs_total_height">156dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-land/config.xml
new file mode 100644
index 0000000..1aa1af3
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-land/config.xml
@@ -0,0 +1,21 @@
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<resources>
+ <dimen name="quick_qs_offset_height">@dimen/status_bar_height_landscape</dimen>
+ <!-- Total height of QQS in landscape, this is effectively status_bar_height_landscape + 128 -->
+ <dimen name="quick_qs_total_height">156dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-land/config.xml
new file mode 100644
index 0000000..1aa1af3
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-land/config.xml
@@ -0,0 +1,21 @@
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<resources>
+ <dimen name="quick_qs_offset_height">@dimen/status_bar_height_landscape</dimen>
+ <!-- Total height of QQS in landscape, this is effectively status_bar_height_landscape + 128 -->
+ <dimen name="quick_qs_total_height">156dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 608970f..f9af31c 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -208,6 +208,10 @@
// Package: android
NOTE_ZEN_UPGRADE = 48;
+ // Notification to suggest automatic battery saver.
+ // Package: android
+ NOTE_AUTO_SAVER_SUGGESTION = 49;
+
// ADD_NEW_IDS_ABOVE_THIS_LINE
// Legacy IDs with arbitrary values appear below
// Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 009e723..9c421c6 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -21,6 +21,7 @@
import static com.android.server.autofill.Helper.bundleToString;
import static com.android.server.autofill.Helper.sDebug;
+import static com.android.server.autofill.Helper.sFullScreenMode;
import static com.android.server.autofill.Helper.sPartitionMaxCount;
import static com.android.server.autofill.Helper.sVisibleDatasetsMaxCount;
import static com.android.server.autofill.Helper.sVerbose;
@@ -449,7 +450,7 @@
}
// Called by Shell command.
- public int getMaxPartitions() {
+ int getMaxPartitions() {
mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
synchronized (mLock) {
@@ -458,7 +459,7 @@
}
// Called by Shell command.
- public void setMaxPartitions(int max) {
+ void setMaxPartitions(int max) {
mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
Slog.i(TAG, "setMaxPartitions(): " + max);
synchronized (mLock) {
@@ -467,7 +468,7 @@
}
// Called by Shell command.
- public int getMaxVisibleDatasets() {
+ int getMaxVisibleDatasets() {
mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
synchronized (mLock) {
@@ -476,7 +477,7 @@
}
// Called by Shell command.
- public void setMaxVisibleDatasets(int max) {
+ void setMaxVisibleDatasets(int max) {
mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
Slog.i(TAG, "setMaxVisibleDatasets(): " + max);
synchronized (mLock) {
@@ -485,7 +486,7 @@
}
// Called by Shell command.
- public void getScore(@Nullable String algorithmName, @NonNull String value1,
+ void getScore(@Nullable String algorithmName, @NonNull String value1,
@NonNull String value2, @NonNull RemoteCallback callback) {
mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
@@ -496,6 +497,18 @@
Arrays.asList(AutofillValue.forText(value1)), new String[] { value2 });
}
+ // Called by Shell command.
+ Boolean getFullScreenMode() {
+ mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
+ return sFullScreenMode;
+ }
+
+ // Called by Shell command.
+ void setFullScreenMode(@Nullable Boolean mode) {
+ mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
+ sFullScreenMode = mode;
+ }
+
private void setDebugLocked(boolean debug) {
com.android.server.autofill.Helper.sDebug = debug;
android.view.autofill.Helper.sDebug = debug;
@@ -1036,6 +1049,18 @@
}
@Override
+ public void setAutofillFailure(int sessionId, @NonNull List<AutofillId> ids, int userId) {
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ if (service != null) {
+ service.setAutofillFailureLocked(sessionId, getCallingUid(), ids);
+ } else if (sVerbose) {
+ Slog.v(TAG, "setAutofillFailure(): no service for " + userId);
+ }
+ }
+ }
+
+ @Override
public void finishSession(int sessionId, int userId) {
synchronized (mLock) {
final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
@@ -1147,6 +1172,9 @@
pw.print("Disabled users: "); pw.println(mDisabledUsers);
pw.print("Max partitions per session: "); pw.println(sPartitionMaxCount);
pw.print("Max visible datasets: "); pw.println(sVisibleDatasetsMaxCount);
+ if (sFullScreenMode != null) {
+ pw.print("Overridden full-screen mode: "); pw.println(sFullScreenMode);
+ }
pw.println("User data constraints: "); UserData.dumpConstraints(prefix, pw);
final int size = mServicesCache.size();
pw.print("Cached services: ");
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index ef0d7e6..0bb29a7 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -404,6 +404,19 @@
}
@GuardedBy("mLock")
+ void setAutofillFailureLocked(int sessionId, int uid, @NonNull List<AutofillId> ids) {
+ if (!isEnabledLocked()) {
+ return;
+ }
+ final Session session = mSessions.get(sessionId);
+ if (session == null || uid != session.uid) {
+ Slog.v(TAG, "setAutofillFailure(): no session for " + sessionId + "(" + uid + ")");
+ return;
+ }
+ session.setAutofillFailureLocked(ids);
+ }
+
+ @GuardedBy("mLock")
void finishSessionLocked(int sessionId, int uid) {
if (!isEnabledLocked()) {
return;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
index 1904061..c76c8ac 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
@@ -80,6 +80,12 @@
pw.println(" get max_visible_datasets");
pw.println(" Gets the maximum number of visible datasets in the UI.");
pw.println("");
+ pw.println(" get full_screen_mode");
+ pw.println(" Gets the Fill UI full screen mode");
+ pw.println("");
+ pw.println(" get fc_score [--algorithm ALGORITHM] value1 value2");
+ pw.println(" Gets the field classification score for 2 fields.");
+ pw.println("");
pw.println(" set log_level [off | debug | verbose]");
pw.println(" Sets the Autofill log level.");
pw.println("");
@@ -89,6 +95,9 @@
pw.println(" set max_visible_datasets number");
pw.println(" Sets the maximum number of visible datasets in the UI.");
pw.println("");
+ pw.println(" set full_screen_mode [true | false | default]");
+ pw.println(" Sets the Fill UI full screen mode");
+ pw.println("");
pw.println(" list sessions [--user USER_ID]");
pw.println(" Lists all pending sessions.");
pw.println("");
@@ -98,9 +107,6 @@
pw.println(" reset");
pw.println(" Resets all pending sessions and cached service connections.");
pw.println("");
- pw.println(" get fc_score [--algorithm ALGORITHM] value1 value2");
- pw.println(" Gets the field classification score for 2 fields.");
- pw.println("");
}
}
@@ -115,6 +121,8 @@
return getMaxVisibileDatasets(pw);
case "fc_score":
return getFieldClassificationScore(pw);
+ case "full_screen_mode":
+ return getFullScreenMode(pw);
default:
pw.println("Invalid set: " + what);
return -1;
@@ -131,6 +139,8 @@
return setMaxPartitions();
case "max_visible_datasets":
return setMaxVisibileDatasets();
+ case "full_screen_mode":
+ return setFullScreenMode(pw);
default:
pw.println("Invalid set: " + what);
return -1;
@@ -219,6 +229,36 @@
return waitForLatch(pw, latch);
}
+ private int getFullScreenMode(PrintWriter pw) {
+ final Boolean mode = mService.getFullScreenMode();
+ if (mode == null) {
+ pw.println("default");
+ } else if (mode) {
+ pw.println("true");
+ } else {
+ pw.println("false");
+ }
+ return 0;
+ }
+
+ private int setFullScreenMode(PrintWriter pw) {
+ final String mode = getNextArgRequired();
+ switch (mode.toLowerCase()) {
+ case "true":
+ mService.setFullScreenMode(Boolean.TRUE);
+ return 0;
+ case "false":
+ mService.setFullScreenMode(Boolean.FALSE);
+ return 0;
+ case "default":
+ mService.setFullScreenMode(null);
+ return 0;
+ default:
+ pw.println("Invalid mode: " + mode);
+ return -1;
+ }
+ }
+
private int requestDestroy(PrintWriter pw) {
if (!isNextArgSessions(pw)) {
return -1;
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 58f78ec..a202aaf 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -70,6 +70,11 @@
*/
public static int sVisibleDatasetsMaxCount = 3;
+ /**
+ * When non-null, overrides whether the UI should be shown on full-screen mode.
+ */
+ public static Boolean sFullScreenMode = null;
+
private Helper() {
throw new UnsupportedOperationException("contains static members only");
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index bcb0bc4..706fb1a 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -1827,6 +1827,11 @@
}
viewState.setState(ViewState.STATE_STARTED_PARTITION);
requestNewFillResponseLocked(flags);
+ } else {
+ if (sVerbose) {
+ Slog.v(TAG, "Not starting new partition for view " + id + ": "
+ + viewState.getStateAsString());
+ }
}
}
@@ -2194,6 +2199,27 @@
}
}
+ /**
+ * Sets the state of views that failed to autofill.
+ */
+ @GuardedBy("mLock")
+ void setAutofillFailureLocked(@NonNull List<AutofillId> ids) {
+ for (int i = 0; i < ids.size(); i++) {
+ final AutofillId id = ids.get(i);
+ final ViewState viewState = mViewStates.get(id);
+ if (viewState == null) {
+ Slog.w(TAG, "setAutofillFailure(): no view for id " + id);
+ continue;
+ }
+ viewState.resetState(ViewState.STATE_AUTOFILLED);
+ final int state = viewState.getState();
+ viewState.setState(state | ViewState.STATE_AUTOFILL_FAILED);
+ if (sVerbose) {
+ Slog.v(TAG, "Changed state of " + id + " to " + viewState.getStateAsString());
+ }
+ }
+ }
+
@GuardedBy("mLock")
private void replaceResponseLocked(@NonNull FillResponse oldResponse,
@NonNull FillResponse newResponse, @Nullable Bundle newClientState) {
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index 97ab97b..9210de2 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -69,6 +69,8 @@
public static final int STATE_RESTARTED_SESSION = 0x100;
/** View is the URL bar of a package on compat mode. */
public static final int STATE_URL_BAR = 0x200;
+ /** View was asked to autofil but failed to do so. */
+ public static final int STATE_AUTOFILL_FAILED = 0x400;
public final AutofillId id;
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index edfc412..25d0d5c 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -17,6 +17,7 @@
import static com.android.server.autofill.Helper.paramsToString;
import static com.android.server.autofill.Helper.sDebug;
+import static com.android.server.autofill.Helper.sFullScreenMode;
import static com.android.server.autofill.Helper.sVerbose;
import android.annotation.AttrRes;
@@ -51,6 +52,7 @@
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.FrameLayout;
+import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RemoteViews;
@@ -118,7 +120,9 @@
private final @NonNull Callback mCallback;
+ private final @Nullable View mHeader;
private final @NonNull ListView mListView;
+ private final @Nullable View mFooter;
private final @Nullable ItemsAdapter mAdapter;
@@ -133,6 +137,10 @@
private boolean mDestroyed;
public static boolean isFullScreen(Context context) {
+ if (sFullScreenMode != null) {
+ if (sVerbose) Slog.v(TAG, "forcing full-screen mode to " + sFullScreenMode);
+ return sFullScreenMode;
+ }
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
}
@@ -145,9 +153,18 @@
final LayoutInflater inflater = LayoutInflater.from(context);
- final ViewGroup decor = (ViewGroup) inflater.inflate(
- mFullScreen ? R.layout.autofill_dataset_picker_fullscreen
- : R.layout.autofill_dataset_picker, null);
+ final RemoteViews headerPresentation = response.getHeader();
+ final RemoteViews footerPresentation = response.getFooter();
+ final ViewGroup decor;
+ if (headerPresentation != null || footerPresentation != null) {
+ decor = (ViewGroup) inflater.inflate(
+ mFullScreen ? R.layout.autofill_dataset_picker_header_footer_fullscreen
+ : R.layout.autofill_dataset_picker_header_footer, null);
+ } else {
+ decor = (ViewGroup) inflater.inflate(
+ mFullScreen ? R.layout.autofill_dataset_picker_fullscreen
+ : R.layout.autofill_dataset_picker, null);
+ }
// if autofill ui is not fullscreen, send unhandled keyevent to app window.
if (!mFullScreen) {
@@ -186,7 +203,9 @@
};
if (response.getAuthentication() != null) {
+ mHeader = null;
mListView = null;
+ mFooter = null;
mAdapter = null;
// insert authentication item under autofill_dataset_container or decor
@@ -207,7 +226,7 @@
decor.setFocusable(true);
decor.setOnClickListener(v -> mCallback.onResponsePicked(response));
- Point maxSize = mTempPoint;
+ final Point maxSize = mTempPoint;
resolveMaxWindowSize(context, maxSize);
// fullScreen mode occupy the full width defined by autofill_dataset_picker_max_width
content.getLayoutParams().width = mFullScreen ? maxSize.x
@@ -226,38 +245,39 @@
requestShowFillUi();
} else {
final int datasetCount = response.getDatasets().size();
-
- // Total items include the (optional) header and footer - we cannot use listview's
- // addHeader() and addFooter() because it would complicate the scrolling logic.
- int totalItems = datasetCount;
-
- RemoteViews.OnClickHandler clickBlocker = null;
- final RemoteViews headerPresentation = response.getHeader();
- View header = null;
- if (headerPresentation != null) {
- clickBlocker = newClickBlocker();
- header = headerPresentation.apply(context, null, clickBlocker);
- totalItems++;
+ if (sVerbose) {
+ Slog.v(TAG, "Number datasets: " + datasetCount + " max visible: "
+ + sVisibleDatasetsMaxCount);
}
- final RemoteViews footerPresentation = response.getFooter();
- View footer = null;
+ RemoteViews.OnClickHandler clickBlocker = null;
+ if (headerPresentation != null) {
+ clickBlocker = newClickBlocker();
+ mHeader = headerPresentation.apply(context, null, clickBlocker);
+ final LinearLayout headerContainer =
+ decor.findViewById(R.id.autofill_dataset_header);
+ if (sVerbose) Slog.v(TAG, "adding header");
+ headerContainer.addView(mHeader);
+ headerContainer.setVisibility(View.VISIBLE);
+ } else {
+ mHeader = null;
+ }
+
if (footerPresentation != null) {
if (clickBlocker == null) { // already set for header
clickBlocker = newClickBlocker();
}
- footer = footerPresentation.apply(context, null, clickBlocker);
- totalItems++;
- }
- if (sVerbose) {
- Slog.v(TAG, "Number datasets: " + datasetCount + " Total items: " + totalItems);
+ mFooter = footerPresentation.apply(context, null, clickBlocker);
+ final LinearLayout footerContainer =
+ decor.findViewById(R.id.autofill_dataset_footer);
+ if (sVerbose) Slog.v(TAG, "adding footer");
+ footerContainer.addView(mFooter);
+ footerContainer.setVisibility(View.VISIBLE);
+ } else {
+ mFooter = null;
}
- final ArrayList<ViewItem> items = new ArrayList<>(totalItems);
- if (header != null) {
- if (sVerbose) Slog.v(TAG, "adding header");
- items.add(new ViewItem(null, null, false, null, header));
- }
+ final ArrayList<ViewItem> items = new ArrayList<>(datasetCount);
for (int i = 0; i < datasetCount; i++) {
final Dataset dataset = response.getDatasets().get(i);
final int index = dataset.getFieldIds().indexOf(focusedViewId);
@@ -299,10 +319,6 @@
items.add(new ViewItem(dataset, filterPattern, filterable, valueText, view));
}
}
- if (footer != null) {
- if (sVerbose) Slog.v(TAG, "adding footer");
- items.add(new ViewItem(null, null, false, null, footer));
- }
mAdapter = new ItemsAdapter(items);
@@ -311,11 +327,6 @@
mListView.setVisibility(View.VISIBLE);
mListView.setOnItemClickListener((adapter, view, position, id) -> {
final ViewItem vi = mAdapter.getItem(position);
- if (vi.dataset == null) {
- // Clicked on header or footer; ignore.
- if (sDebug) Slog.d(TAG, "Ignoring click on item " + position + ": " + view);
- return;
- }
mCallback.onDatasetPicked(vi.dataset);
});
@@ -460,6 +471,13 @@
changed = true;
mContentWidth = maxSize.x;
}
+
+ if (mHeader != null) {
+ mHeader.measure(widthMeasureSpec, heightMeasureSpec);
+ changed |= updateWidth(mHeader, maxSize);
+ changed |= updateHeight(mHeader, maxSize);
+ }
+
for (int i = 0; i < itemCount; i++) {
final View view = mAdapter.getItem(i).view;
view.measure(widthMeasureSpec, heightMeasureSpec);
@@ -473,23 +491,40 @@
break;
}
} else {
- final int clampedMeasuredWidth = Math.min(view.getMeasuredWidth(), maxSize.x);
- final int newContentWidth = Math.max(mContentWidth, clampedMeasuredWidth);
- if (newContentWidth != mContentWidth) {
- mContentWidth = newContentWidth;
- changed = true;
- }
- // Update the width to fit only the first items up to max count
+ changed |= updateWidth(view, maxSize);
if (i < sVisibleDatasetsMaxCount) {
- final int clampedMeasuredHeight = Math.min(view.getMeasuredHeight(), maxSize.y);
- final int newContentHeight = mContentHeight + clampedMeasuredHeight;
- if (newContentHeight != mContentHeight) {
- mContentHeight = newContentHeight;
- changed = true;
- }
+ changed |= updateHeight(view, maxSize);
}
}
}
+
+ if (mFooter != null) {
+ mFooter.measure(widthMeasureSpec, heightMeasureSpec);
+ changed |= updateWidth(mFooter, maxSize);
+ changed |= updateHeight(mFooter, maxSize);
+ }
+ return changed;
+ }
+
+ private boolean updateWidth(View view, Point maxSize) {
+ boolean changed = false;
+ final int clampedMeasuredWidth = Math.min(view.getMeasuredWidth(), maxSize.x);
+ final int newContentWidth = Math.max(mContentWidth, clampedMeasuredWidth);
+ if (newContentWidth != mContentWidth) {
+ mContentWidth = newContentWidth;
+ changed = true;
+ }
+ return changed;
+ }
+
+ private boolean updateHeight(View view, Point maxSize) {
+ boolean changed = false;
+ final int clampedMeasuredHeight = Math.min(view.getMeasuredHeight(), maxSize.y);
+ final int newContentHeight = mContentHeight + clampedMeasuredHeight;
+ if (newContentHeight != mContentHeight) {
+ mContentHeight = newContentHeight;
+ changed = true;
+ }
return changed;
}
@@ -501,7 +536,7 @@
private static void resolveMaxWindowSize(Context context, Point outPoint) {
context.getDisplay().getSize(outPoint);
- TypedValue typedValue = sTempTypedValue;
+ final TypedValue typedValue = sTempTypedValue;
context.getTheme().resolveAttribute(R.attr.autofillDatasetPickerMaxWidth,
typedValue, true);
outPoint.x = (int) typedValue.getFraction(outPoint.x, outPoint.x);
@@ -688,17 +723,27 @@
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("mCallback: "); pw.println(mCallback != null);
pw.print(prefix); pw.print("mFullScreen: "); pw.println(mFullScreen);
- pw.print(prefix); pw.print("mListView: "); pw.println(mListView);
- pw.print(prefix); pw.print("mAdapter: "); pw.println(mAdapter);
- pw.print(prefix); pw.print("mFilterText: ");
- Helper.printlnRedactedText(pw, mFilterText);
+ if (mHeader != null) {
+ pw.print(prefix); pw.print("mHeader: "); pw.println(mHeader);
+ }
+ if (mListView != null) {
+ pw.print(prefix); pw.print("mListView: "); pw.println(mListView);
+ }
+ if (mFooter != null) {
+ pw.print(prefix); pw.print("mFooter: "); pw.println(mFooter);
+ }
+ if (mAdapter != null) {
+ pw.print(prefix); pw.print("mAdapter: "); pw.println(mAdapter);
+ }
+ if (mFilterText != null) {
+ pw.print(prefix); pw.print("mFilterText: ");
+ Helper.printlnRedactedText(pw, mFilterText);
+ }
pw.print(prefix); pw.print("mContentWidth: "); pw.println(mContentWidth);
pw.print(prefix); pw.print("mContentHeight: "); pw.println(mContentHeight);
pw.print(prefix); pw.print("mDestroyed: "); pw.println(mDestroyed);
- pw.print(prefix); pw.print("mWindow: ");
- if (mWindow == null) {
- pw.println("N/A");
- } else {
+ if (mWindow != null) {
+ pw.print(prefix); pw.print("mWindow: ");
final String prefix2 = prefix + " ";
pw.println();
pw.print(prefix2); pw.print("showing: "); pw.println(mWindow.mShowing);
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 539c001..83fe976 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1753,7 +1753,8 @@
long token = Binder.clearCallingIdentity();
try {
return LocationAccessPolicy.canAccessCellLocation(mContext,
- r.callingPackage, r.callerUid, r.callerPid);
+ r.callingPackage, r.callerUid, r.callerPid,
+ /*throwOnDeniedPermission*/ false);
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5131a93..e3584e6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -820,7 +820,7 @@
public boolean canShowErrorDialogs() {
return mShowDialogs && !mSleeping && !mShuttingDown
- && !mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)
+ && !mKeyguardController.isKeyguardOrAodShowing(DEFAULT_DISPLAY)
&& !mUserController.hasUserRestriction(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
mUserController.getCurrentUserId())
&& !(UserManager.isDeviceInDemoMode(mContext)
@@ -1262,8 +1262,12 @@
}
public static GrantUri resolve(int defaultSourceUserHandle, Uri uri) {
- return new GrantUri(ContentProvider.getUserIdFromUri(uri, defaultSourceUserHandle),
- ContentProvider.getUriWithoutUserId(uri), false);
+ if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
+ return new GrantUri(ContentProvider.getUserIdFromUri(uri, defaultSourceUserHandle),
+ ContentProvider.getUriWithoutUserId(uri), false);
+ } else {
+ return new GrantUri(defaultSourceUserHandle, uri, false);
+ }
}
}
@@ -10601,8 +10605,8 @@
intent.addFlags(Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
}
}
- final ActivityInfo ainfo = AppGlobals.getPackageManager().getActivityInfo(comp, 0,
- UserHandle.getUserId(callingUid));
+ final ActivityInfo ainfo = AppGlobals.getPackageManager().getActivityInfo(comp,
+ STOCK_PM_FLAGS, UserHandle.getUserId(callingUid));
if (ainfo.applicationInfo.uid != callingUid) {
throw new SecurityException(
"Can't add task for another application: target uid="
@@ -13046,6 +13050,22 @@
return mSleeping;
}
+ void reportGlobalUsageEventLocked(int event) {
+ mUsageStatsService.reportEvent("android", mUserController.getCurrentUserId(), event);
+ int[] profiles = mUserController.getCurrentProfileIds();
+ if (profiles != null) {
+ for (int i = profiles.length - 1; i >= 0; i--) {
+ mUsageStatsService.reportEvent((String)null, profiles[i], event);
+ }
+ }
+ }
+
+ void reportCurWakefulnessUsageEventLocked() {
+ reportGlobalUsageEventLocked(mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE
+ ? UsageEvents.Event.SCREEN_INTERACTIVE
+ : UsageEvents.Event.SCREEN_NON_INTERACTIVE);
+ }
+
void onWakefulnessChanged(int wakefulness) {
synchronized(this) {
boolean wasAwake = mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE;
@@ -13055,6 +13075,7 @@
if (wasAwake != isAwake) {
// Also update state in a special way for running foreground services UI.
mServices.updateScreenStateLocked(isAwake);
+ reportCurWakefulnessUsageEventLocked();
mHandler.obtainMessage(DISPATCH_SCREEN_AWAKE_MSG, isAwake ? 1 : 0, 0)
.sendToTarget();
}
@@ -13202,7 +13223,8 @@
}
@Override
- public void setLockScreenShown(boolean showing, int secondaryDisplayShowing) {
+ public void setLockScreenShown(boolean keyguardShowing, boolean aodShowing,
+ int secondaryDisplayShowing) {
if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires permission "
@@ -13212,13 +13234,14 @@
synchronized(this) {
long ident = Binder.clearCallingIdentity();
try {
- mKeyguardController.setKeyguardShown(showing, secondaryDisplayShowing);
+ mKeyguardController.setKeyguardShown(keyguardShowing, aodShowing,
+ secondaryDisplayShowing);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
- mHandler.obtainMessage(DISPATCH_SCREEN_KEYGUARD_MSG, showing ? 1 : 0, 0)
+ mHandler.obtainMessage(DISPATCH_SCREEN_KEYGUARD_MSG, keyguardShowing ? 1 : 0, 0)
.sendToTarget();
}
@@ -14029,6 +14052,18 @@
}
@Override
+ public boolean isUidActive(int uid, String callingPackage) {
+ if (!hasUsageStatsPermission(callingPackage)) {
+ enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS,
+ "getPackageProcessState");
+ }
+ synchronized (this) {
+ final UidRecord uidRecord = mActiveUids.get(uid);
+ return uidRecord != null && !uidRecord.setIdle;
+ }
+ }
+
+ @Override
public boolean convertFromTranslucent(IBinder token) {
final long origId = Binder.clearCallingIdentity();
try {
@@ -21190,7 +21225,7 @@
ApplicationInfo aInfo = null;
try {
aInfo = AppGlobals.getPackageManager()
- .getApplicationInfo(ssp, 0 /*flags*/, userId);
+ .getApplicationInfo(ssp, STOCK_PM_FLAGS, userId);
} catch (RemoteException ignore) {}
if (aInfo == null) {
Slog.w(TAG, "Dropping ACTION_PACKAGE_REPLACED for non-existent pkg:"
@@ -21215,7 +21250,7 @@
try {
ApplicationInfo ai = AppGlobals.getPackageManager().
- getApplicationInfo(ssp, 0, 0);
+ getApplicationInfo(ssp, STOCK_PM_FLAGS, 0);
mBatteryStatsService.notePackageInstalled(ssp,
ai != null ? ai.versionCode : 0);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index ccc17a3..1af4114 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -236,7 +236,8 @@
final IApplicationToken.Stub appToken; // window manager token
AppWindowContainerController mWindowContainerController;
final ActivityInfo info; // all about me
- final ApplicationInfo appInfo; // information about activity's app
+ // TODO: This is duplicated state already contained in info.applicationInfo - remove
+ ApplicationInfo appInfo; // information about activity's app
final int launchedFromPid; // always the pid who started the activity.
final int launchedFromUid; // always the uid who started the activity.
final String launchedFromPackage; // always the package who started the activity.
@@ -605,6 +606,11 @@
}
}
+ void updateApplicationInfo(ApplicationInfo aInfo) {
+ appInfo = aInfo;
+ info.applicationInfo = aInfo;
+ }
+
private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
return crossesSizeThreshold(mHorizontalSizeConfigurations, firstDp, secondDp);
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index aa462ec..00ebcbd 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1324,7 +1324,7 @@
final ActivityRecord ar = activities.get(activityNdx);
if ((userId == ar.userId) && packageName.equals(ar.packageName)) {
- ar.info.applicationInfo = aInfo;
+ ar.updateApplicationInfo(aInfo);
}
}
}
@@ -2019,8 +2019,9 @@
* @return true if {@param r} is visible taken Keyguard state into account, false otherwise
*/
boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible, boolean isTop) {
- final boolean keyguardShowing = mStackSupervisor.getKeyguardController().isKeyguardShowing(
- mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY);
+ final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
+ final boolean keyguardOrAodShowing = mStackSupervisor.getKeyguardController()
+ .isKeyguardOrAodShowing(displayId);
final boolean keyguardLocked = mStackSupervisor.getKeyguardController().isKeyguardLocked();
final boolean showWhenLocked = r.canShowWhenLocked();
final boolean dismissKeyguard = r.hasDismissKeyguardWindows();
@@ -2041,10 +2042,9 @@
return true;
}
}
- if (keyguardShowing) {
-
+ if (keyguardOrAodShowing) {
// If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard
- // right away.
+ // right away and AOD isn't visible.
return shouldBeVisible && mStackSupervisor.getKeyguardController()
.canShowActivityWhileKeyguardShowing(r, dismissKeyguard);
} else if (keyguardLocked) {
@@ -3987,7 +3987,8 @@
} else {
try {
ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
- destIntent.getComponent(), 0, srec.userId);
+ destIntent.getComponent(), ActivityManagerService.STOCK_PM_FLAGS,
+ srec.userId);
// TODO(b/64750076): Check if calling pid should really be -1.
final int res = mService.getActivityStartController()
.obtainStarter(destIntent, "navigateUpTo")
@@ -5139,8 +5140,9 @@
mService, taskId, info, intent, voiceSession, voiceInteractor);
// add the task to stack first, mTaskPositioner might need the stack association
addTask(task, toTop, "createTaskRecord");
+ final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController()
- .isKeyguardShowing(mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY);
+ .isKeyguardOrAodShowing(displayId);
if (!mStackSupervisor.getLaunchParamsController()
.layoutTask(task, info.windowLayout, activity, source, options)
&& !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 265e4fa..d5dfdcf 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -3382,8 +3382,8 @@
stack.goToSleepIfPossible(false /* shuttingDown */);
} else {
stack.awakeFromSleepingLocked();
- if (isFocusedStack(stack)
- && !getKeyguardController().isKeyguardShowing(display.mDisplayId)) {
+ if (isFocusedStack(stack) && !getKeyguardController().isKeyguardOrAodShowing(
+ display.mDisplayId)) {
// If the keyguard is unlocked - resume immediately.
// It is possible that the display will not be awake at the time we
// process the keyguard going away, which can happen before the sleep token
diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index 868f90d..fb78838 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -198,9 +198,10 @@
// See if we should be showing the platform update setup UI.
final Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
- final List<ResolveInfo> ris = mService.mContext.getPackageManager()
- .queryIntentActivities(intent,
- PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_META_DATA);
+ final List<ResolveInfo> ris =
+ mService.mContext.getPackageManager().queryIntentActivities(intent,
+ PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_META_DATA
+ | ActivityManagerService.STOCK_PM_FLAGS);
if (!ris.isEmpty()) {
final ResolveInfo ri = ris.get(0);
String vers = ri.activityInfo.metaData != null
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 3c49ece..b338029 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -17,10 +17,15 @@
package com.android.server.am;
import android.app.ActivityManager;
+import android.app.job.JobProtoEnums;
import android.bluetooth.BluetoothActivityEnergyInfo;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.hardware.usb.UsbManager;
import android.net.wifi.WifiActivityEnergyInfo;
import android.os.PowerManager.ServiceType;
import android.os.PowerSaveState;
@@ -34,6 +39,7 @@
import android.os.ParcelFormatException;
import android.os.PowerManagerInternal;
import android.os.Process;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -70,7 +76,6 @@
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
@@ -438,6 +443,8 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteSyncStartLocked(name, uid);
+ StatsLog.write_non_chained(StatsLog.SYNC_STATE_CHANGED, uid, null, name,
+ StatsLog.SYNC_STATE_CHANGED__STATE__ON);
}
}
@@ -445,6 +452,8 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteSyncFinishLocked(name, uid);
+ StatsLog.write_non_chained(StatsLog.SYNC_STATE_CHANGED, uid, null, name,
+ StatsLog.SYNC_STATE_CHANGED__STATE__OFF);
}
}
@@ -452,6 +461,9 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteJobStartLocked(name, uid);
+ StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED, uid, null,
+ name, StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__STARTED,
+ JobProtoEnums.STOP_REASON_UNKNOWN);
}
}
@@ -459,6 +471,9 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteJobFinishLocked(name, uid, stopReason);
+ StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED, uid, null,
+ name, StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__FINISHED,
+ stopReason);
}
}
@@ -573,6 +588,8 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteStartSensorLocked(uid, sensor);
+ StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, uid, null, sensor,
+ StatsLog.SENSOR_STATE_CHANGED__STATE__ON);
}
}
@@ -580,6 +597,8 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteStopSensorLocked(uid, sensor);
+ StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, uid, null,
+ sensor, StatsLog.SENSOR_STATE_CHANGED__STATE__OFF);
}
}
@@ -684,6 +703,13 @@
}
}
+ public void noteUsbConnectionState(boolean connected) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteUsbConnectionStateLocked(connected);
+ }
+ }
+
public void notePhoneSignalStrength(SignalStrength signalStrength) {
enforceCallingPermission();
synchronized (mStats) {
@@ -724,6 +750,8 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteAudioOnLocked(uid);
+ StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, uid, null,
+ StatsLog.AUDIO_STATE_CHANGED__STATE__ON);
}
}
@@ -731,6 +759,8 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteAudioOffLocked(uid);
+ StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, uid, null,
+ StatsLog.AUDIO_STATE_CHANGED__STATE__OFF);
}
}
@@ -738,6 +768,8 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteVideoOnLocked(uid);
+ StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, uid, null,
+ StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED__STATE__ON);
}
}
@@ -745,6 +777,8 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteVideoOffLocked(uid);
+ StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, uid,
+ null, StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED__STATE__OFF);
}
}
@@ -752,6 +786,8 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteResetAudioLocked();
+ StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, -1, null,
+ StatsLog.AUDIO_STATE_CHANGED__STATE__RESET);
}
}
@@ -759,6 +795,8 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteResetVideoLocked();
+ StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, -1, null,
+ StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED__STATE__RESET);
}
}
@@ -766,6 +804,8 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteFlashlightOnLocked(uid);
+ StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, uid, null,
+ StatsLog.FLASHLIGHT_STATE_CHANGED__STATE__ON);
}
}
@@ -773,6 +813,8 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteFlashlightOffLocked(uid);
+ StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, uid, null,
+ StatsLog.FLASHLIGHT_STATE_CHANGED__STATE__OFF);
}
}
@@ -781,6 +823,8 @@
if (DBG) Slog.d(TAG, "begin noteStartCamera");
synchronized (mStats) {
mStats.noteCameraOnLocked(uid);
+ StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, uid, null,
+ StatsLog.CAMERA_STATE_CHANGED__STATE__ON);
}
if (DBG) Slog.d(TAG, "end noteStartCamera");
}
@@ -789,6 +833,8 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteCameraOffLocked(uid);
+ StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, uid, null,
+ StatsLog.CAMERA_STATE_CHANGED__STATE__OFF);
}
}
@@ -796,6 +842,8 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteResetCameraLocked();
+ StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, -1, null,
+ StatsLog.CAMERA_STATE_CHANGED__STATE__RESET);
}
}
@@ -803,6 +851,8 @@
enforceCallingPermission();
synchronized (mStats) {
mStats.noteResetFlashlightLocked();
+ StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, -1, null,
+ StatsLog.FLASHLIGHT_STATE_CHANGED__STATE__RESET);
}
}
@@ -1116,6 +1166,35 @@
Binder.getCallingPid(), Binder.getCallingUid(), null);
}
+ public final static class UsbConnectionReceiver extends BroadcastReceiver {
+ private static final String TAG = UsbConnectionReceiver.class.getSimpleName();
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
+ final Intent usbState = context.registerReceiver(null, new IntentFilter(UsbManager.ACTION_USB_STATE));
+ if (usbState != null) {
+ handleUsbState(usbState);
+ }
+ } else if (UsbManager.ACTION_USB_STATE.equals(action)) {
+ handleUsbState(intent);
+ }
+ }
+ private void handleUsbState(Intent intent) {
+ IBatteryStats bs = getService();
+ if (bs == null) {
+ Slog.w(TAG, "Could not access batterystats");
+ return;
+ }
+ boolean connected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED);
+ try {
+ bs.noteUsbConnectionState(connected);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Could not access batterystats: ", e);
+ }
+ }
+ }
+
final class WakeupReasonThread extends Thread {
private static final int MAX_REASON_SIZE = 512;
private CharsetDecoder mDecoder;
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index b67dd0d..1b7f75b 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -62,6 +62,7 @@
private final ActivityStackSupervisor mStackSupervisor;
private WindowManagerService mWindowManager;
private boolean mKeyguardShowing;
+ private boolean mAodShowing;
private boolean mKeyguardGoingAway;
private boolean mOccluded;
private boolean mDismissalRequested;
@@ -82,6 +83,15 @@
}
/**
+ * @return true if either Keyguard or AOD are showing, not going away, and not being occluded
+ * on the given display, false otherwise
+ */
+ boolean isKeyguardOrAodShowing(int displayId) {
+ return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway &&
+ (displayId == DEFAULT_DISPLAY ? !mOccluded : displayId == mSecondaryDisplayShowing);
+ }
+
+ /**
* @return true if Keyguard is showing, not going away, and not being occluded on the given
* display, false otherwise
*/
@@ -108,17 +118,19 @@
/**
* Update the Keyguard showing state.
*/
- void setKeyguardShown(boolean showing, int secondaryDisplayShowing) {
- boolean showingChanged = showing != mKeyguardShowing;
+ void setKeyguardShown(boolean keyguardShowing, boolean aodShowing,
+ int secondaryDisplayShowing) {
+ boolean showingChanged = keyguardShowing != mKeyguardShowing || aodShowing != mAodShowing;
if (!showingChanged && secondaryDisplayShowing == mSecondaryDisplayShowing) {
return;
}
- mKeyguardShowing = showing;
+ mKeyguardShowing = keyguardShowing;
+ mAodShowing = aodShowing;
mSecondaryDisplayShowing = secondaryDisplayShowing;
if (showingChanged) {
dismissDockedStackIfNeeded();
setKeyguardGoingAway(false);
- if (showing) {
+ if (keyguardShowing) {
mDismissalRequested = false;
}
}
@@ -230,8 +242,8 @@
// Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is
// already the dismissing activity, in which case we don't allow it to repeatedly dismiss
// Keyguard.
- return dismissKeyguard && canDismissKeyguard() &&
- (mDismissalRequested || r != mDismissingKeyguardActivity);
+ return dismissKeyguard && canDismissKeyguard() && !mAodShowing
+ && (mDismissalRequested || r != mDismissingKeyguardActivity);
}
/**
@@ -369,9 +381,9 @@
}
private void updateKeyguardSleepToken() {
- if (mSleepToken == null && isKeyguardShowing(DEFAULT_DISPLAY)) {
+ if (mSleepToken == null && isKeyguardOrAodShowing(DEFAULT_DISPLAY)) {
mSleepToken = mService.acquireSleepToken("Keyguard", DEFAULT_DISPLAY);
- } else if (mSleepToken != null && !isKeyguardShowing(DEFAULT_DISPLAY)) {
+ } else if (mSleepToken != null && !isKeyguardOrAodShowing(DEFAULT_DISPLAY)) {
mSleepToken.release();
mSleepToken = null;
}
@@ -380,6 +392,7 @@
void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "KeyguardController:");
pw.println(prefix + " mKeyguardShowing=" + mKeyguardShowing);
+ pw.println(prefix + " mAodShowing=" + mAodShowing);
pw.println(prefix + " mKeyguardGoingAway=" + mKeyguardGoingAway);
pw.println(prefix + " mOccluded=" + mOccluded);
pw.println(prefix + " mDismissingKeyguardActivity=" + mDismissingKeyguardActivity);
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index efd8153..fcf00ce 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -600,7 +600,8 @@
// activities that are fully runnable based on
// current system state.
ai = pm.getActivityInfo(task.realActivity,
- PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING
+ | ActivityManagerService.STOCK_PM_FLAGS, userId);
} catch (RemoteException e) {
// Will never happen.
continue;
diff --git a/services/core/java/com/android/server/am/RecentsAnimation.java b/services/core/java/com/android/server/am/RecentsAnimation.java
index da56ffd..73a7c3eb 100644
--- a/services/core/java/com/android/server/am/RecentsAnimation.java
+++ b/services/core/java/com/android/server/am/RecentsAnimation.java
@@ -168,7 +168,7 @@
"RecentsAnimation#onAnimationFinished_inSurfaceTransaction");
mWindowManager.deferSurfaceLayout();
try {
- mWindowManager.cleanupRecentsAnimation();
+ mWindowManager.cleanupRecentsAnimation(moveHomeToTop);
// Move the home stack to the front
final ActivityRecord homeActivity = mStackSupervisor.getHomeActivity();
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 0d125e0..f710690 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -47,6 +47,7 @@
import android.app.IStopUserCallback;
import android.app.IUserSwitchObserver;
import android.app.KeyguardManager;
+import android.app.usage.UsageEvents;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.Intent;
@@ -959,6 +960,8 @@
mInjector.getUserManagerInternal().setUserState(userId, uss.state);
}
if (foreground) {
+ // Make sure the old user is no longer considering the display to be on.
+ mInjector.reportGlobalUsageEventLocked(UsageEvents.Event.SCREEN_NON_INTERACTIVE);
synchronized (mLock) {
mCurrentUserId = userId;
mTargetUserId = UserHandle.USER_NULL; // reset, mCurrentUserId has caught up
@@ -966,6 +969,7 @@
mInjector.updateUserConfiguration();
updateCurrentProfileIds();
mInjector.getWindowManager().setCurrentUser(userId, getCurrentProfileIds());
+ mInjector.reportCurWakefulnessUsageEvent();
// Once the internal notion of the active user has switched, we lock the device
// with the option to show the user switcher on the keyguard.
if (mUserSwitchUiEnabled) {
@@ -2183,6 +2187,18 @@
d.show();
}
+ void reportGlobalUsageEventLocked(int event) {
+ synchronized (mService) {
+ mService.reportGlobalUsageEventLocked(event);
+ }
+ }
+
+ void reportCurWakefulnessUsageEvent() {
+ synchronized (mService) {
+ mService.reportCurWakefulnessUsageEventLocked();
+ }
+ }
+
void stackSupervisorRemoveUser(int userId) {
synchronized (mService) {
mService.mStackSupervisor.removeUserLocked(userId);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 041764f..c8b6b50 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1422,21 +1422,24 @@
direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
.append("/").append(caller).append(" uid:").append(uid).toString()));
final int streamType;
- if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
- streamType = mVolumeControlStream;
- } else {
- final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
- final boolean activeForReal;
- if (maybeActiveStreamType == AudioSystem.STREAM_RING
- || maybeActiveStreamType == AudioSystem.STREAM_NOTIFICATION) {
- activeForReal = wasStreamActiveRecently(maybeActiveStreamType, 0);
- } else {
- activeForReal = AudioSystem.isStreamActive(maybeActiveStreamType, 0);
- }
- if (activeForReal || mVolumeControlStream == -1) {
- streamType = maybeActiveStreamType;
- } else {
+ synchronized (mForceControlStreamLock) {
+ // Request lock in case mVolumeControlStream is changed by other thread.
+ if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
streamType = mVolumeControlStream;
+ } else {
+ final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
+ final boolean activeForReal;
+ if (maybeActiveStreamType == AudioSystem.STREAM_RING
+ || maybeActiveStreamType == AudioSystem.STREAM_NOTIFICATION) {
+ activeForReal = wasStreamActiveRecently(maybeActiveStreamType, 0);
+ } else {
+ activeForReal = AudioSystem.isStreamActive(maybeActiveStreamType, 0);
+ }
+ if (activeForReal || mVolumeControlStream == -1) {
+ streamType = maybeActiveStreamType;
+ } else {
+ streamType = mVolumeControlStream;
+ }
}
}
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 711d40b..4313d17 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -60,14 +60,8 @@
int[] backlightRange = resources.getIntArray(
com.android.internal.R.array.config_screenBrightnessBacklight);
- float[] minimumBrightnessCurveLux = getLuxLevels(resources.getIntArray(
- com.android.internal.R.array.config_autoBrightnessMinimumBrightnessCurveLux));
- float[] minimumBrightnessCurveNits = getFloatArray(resources.obtainTypedArray(
- com.android.internal.R.array.config_autoBrightnessMinimumBrightnessCurveNits));
-
if (isValidMapping(nitsRange, backlightRange)
- && isValidMapping(luxLevels, brightnessLevelsNits)
- && isValidMapping(minimumBrightnessCurveLux, minimumBrightnessCurveNits)) {
+ && isValidMapping(luxLevels, brightnessLevelsNits)) {
int minimumBacklight = resources.getInteger(
com.android.internal.R.integer.config_screenBrightnessSettingMinimum);
int maximumBacklight = resources.getInteger(
@@ -79,8 +73,7 @@
}
BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
builder.setCurve(luxLevels, brightnessLevelsNits);
- return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange,
- minimumBrightnessCurveLux, minimumBrightnessCurveNits);
+ return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange);
} else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) {
return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight);
} else {
@@ -455,11 +448,8 @@
private float mUserLux;
private float mUserBrightness;
- private final Spline mMinimumBrightnessCurve;
-
public PhysicalMappingStrategy(BrightnessConfiguration config,
- float[] nits, int[] backlight, float[] minimumBrightnessCurveLux,
- float[] minimumBrightnessCurveNits) {
+ float[] nits, int[] backlight) {
Preconditions.checkArgument(nits.length != 0 && backlight.length != 0,
"Nits and backlight arrays must not be empty!");
Preconditions.checkArgument(nits.length == backlight.length,
@@ -479,9 +469,6 @@
normalizedBacklight[i] = normalizeAbsoluteBrightness(backlight[i]);
}
- mMinimumBrightnessCurve = Spline.createSpline(
- minimumBrightnessCurveLux, minimumBrightnessCurveNits);
-
mNitsToBacklightSpline = createSpline(nits, normalizedBacklight);
mBacklightToNitsSpline = createSpline(normalizedBacklight, nits);
@@ -497,7 +484,7 @@
if (config.equals(mConfig)) {
return false;
}
- validateBrightnessConfiguration(config);
+
Pair<float[], float[]> curve = config.getCurve();
mBrightnessSpline = createSpline(curve.first /*lux*/, curve.second /*nits*/);
mConfig = config;
@@ -562,24 +549,5 @@
pw.println(" mUserLux=" + mUserLux);
pw.println(" mUserBrightness=" + mUserBrightness);
}
-
- private void validateBrightnessConfiguration(BrightnessConfiguration config) {
- Pair<float[], float[]> curve = config.getCurve();
- Spline brightnessSpline = Spline.createSpline(curve.first, curve.second);
- if (isBrightnessSplineTooDark(brightnessSpline)) {
- throw new IllegalArgumentException("brightness curve is too dark");
- }
- }
-
- private boolean isBrightnessSplineTooDark(Spline brightnessSpline) {
- float[] lux = mDefaultConfig.getCurve().first;
- for (int i = 0; i < lux.length; i++) {
- if (brightnessSpline.interpolate(lux[i]) <
- mMinimumBrightnessCurve.interpolate(lux[i])) {
- return true;
- }
- }
- return false;
- }
}
}
diff --git a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
index a52dd0b..8be2c9e 100644
--- a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
+++ b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
@@ -18,10 +18,10 @@
import android.content.Context;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
+import android.hardware.biometrics.BiometricDialog;
+import android.hardware.biometrics.IBiometricDialogReceiver;
import android.hardware.fingerprint.Fingerprint;
-import android.hardware.fingerprint.FingerprintDialog;
import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.IFingerprintDialogReceiver;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
import android.os.Bundle;
import android.os.IBinder;
@@ -46,22 +46,22 @@
public static final int LOCKOUT_PERMANENT = 2;
// Callback mechanism received from the client
- // (FingerprintDialog -> FingerprintManager -> FingerprintService -> AuthenticationClient)
- private IFingerprintDialogReceiver mDialogReceiverFromClient;
+ // (BiometricDialog -> FingerprintManager -> FingerprintService -> AuthenticationClient)
+ private IBiometricDialogReceiver mDialogReceiverFromClient;
private Bundle mBundle;
private IStatusBarService mStatusBarService;
private boolean mInLockout;
private final FingerprintManager mFingerprintManager;
protected boolean mDialogDismissed;
- // Receives events from SystemUI
- protected IFingerprintDialogReceiver mDialogReceiver = new IFingerprintDialogReceiver.Stub() {
+ // Receives events from SystemUI and handles them before forwarding them to FingerprintDialog
+ protected IBiometricDialogReceiver mDialogReceiver = new IBiometricDialogReceiver.Stub() {
@Override // binder call
public void onDialogDismissed(int reason) {
if (mBundle != null && mDialogReceiverFromClient != null) {
try {
mDialogReceiverFromClient.onDialogDismissed(reason);
- if (reason == FingerprintDialog.DISMISSED_REASON_USER_CANCEL) {
+ if (reason == BiometricDialog.DISMISSED_REASON_USER_CANCEL) {
onError(FingerprintManager.FINGERPRINT_ERROR_USER_CANCELED,
0 /* vendorCode */);
}
@@ -88,7 +88,7 @@
public AuthenticationClient(Context context, long halDeviceId, IBinder token,
IFingerprintServiceReceiver receiver, int targetUserId, int groupId, long opId,
boolean restricted, String owner, Bundle bundle,
- IFingerprintDialogReceiver dialogReceiver, IStatusBarService statusBarService) {
+ IBiometricDialogReceiver dialogReceiver, IStatusBarService statusBarService) {
super(context, halDeviceId, token, receiver, targetUserId, groupId, restricted, owner);
mOpId = opId;
mBundle = bundle;
@@ -299,7 +299,7 @@
// If the user already cancelled authentication (via some interaction with the
// dialog, we do not need to hide it since it's already hidden.
// If the device is in lockout, don't hide the dialog - it will automatically hide
- // after FingerprintDialog.HIDE_DIALOG_DELAY
+ // after BiometricDialog.HIDE_DIALOG_DELAY
if (mBundle != null && !mDialogDismissed && !mInLockout) {
try {
mStatusBarService.hideFingerprintDialog();
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index fc8aace..530b6f6 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -19,6 +19,7 @@
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.MANAGE_FINGERPRINT;
import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
+import static android.Manifest.permission.USE_BIOMETRIC;
import static android.Manifest.permission.USE_FINGERPRINT;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
@@ -37,12 +38,12 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
+import android.hardware.biometrics.IBiometricDialogReceiver;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprintClientCallback;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.IFingerprintClientActiveCallback;
-import android.hardware.fingerprint.IFingerprintDialogReceiver;
import android.hardware.fingerprint.IFingerprintService;
import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
@@ -778,7 +779,11 @@
*/
private boolean canUseFingerprint(String opPackageName, boolean requireForeground, int uid,
int pid, int userId) {
- checkPermission(USE_FINGERPRINT);
+ if (getContext().checkCallingPermission(USE_FINGERPRINT)
+ != PackageManager.PERMISSION_GRANTED) {
+ checkPermission(USE_BIOMETRIC);
+ }
+
if (isKeyguard(opPackageName)) {
return true; // Keyguard is always allowed
}
@@ -845,7 +850,7 @@
private void startAuthentication(IBinder token, long opId, int callingUserId, int groupId,
IFingerprintServiceReceiver receiver, int flags, boolean restricted,
- String opPackageName, Bundle bundle, IFingerprintDialogReceiver dialogReceiver) {
+ String opPackageName, Bundle bundle, IBiometricDialogReceiver dialogReceiver) {
updateActiveGroup(groupId, opPackageName);
if (DEBUG) Slog.v(TAG, "startAuthentication(" + opPackageName + ")");
@@ -1156,7 +1161,7 @@
public void authenticate(final IBinder token, final long opId, final int groupId,
final IFingerprintServiceReceiver receiver, final int flags,
final String opPackageName, final Bundle bundle,
- final IFingerprintDialogReceiver dialogReceiver) {
+ final IBiometricDialogReceiver dialogReceiver) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final int callingUserId = UserHandle.getCallingUserId();
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index a87adbd..050c1f4 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -19,10 +19,12 @@
import static android.security.keystore.recovery.KeyChainProtectionParams.TYPE_LOCKSCREEN;
import android.annotation.Nullable;
+import android.annotation.NonNull;
import android.content.Context;
-import android.security.keystore.recovery.KeyDerivationParams;
import android.security.keystore.recovery.KeyChainProtectionParams;
import android.security.keystore.recovery.KeyChainSnapshot;
+import android.security.keystore.recovery.KeyDerivationParams;
+import android.security.keystore.recovery.TrustedRootCertificates;
import android.security.keystore.recovery.WrappedApplicationKey;
import android.util.Log;
@@ -185,8 +187,12 @@
}
PublicKey publicKey;
+ String rootCertAlias =
+ mRecoverableKeyStoreDb.getActiveRootOfTrust(mUserId, recoveryAgentUid);
+
+ rootCertAlias = replaceEmptyValueWithSecureDefault(rootCertAlias);
CertPath certPath = mRecoverableKeyStoreDb.getRecoveryServiceCertPath(mUserId,
- recoveryAgentUid);
+ recoveryAgentUid, rootCertAlias);
if (certPath != null) {
Log.d(TAG, "Using the public key in stored CertPath for syncing");
publicKey = certPath.getCertificates().get(0).getPublicKey();
@@ -206,6 +212,14 @@
return;
}
+ // The only place in this class which uses credential value
+ if (!TrustedRootCertificates.GOOGLE_CLOUD_KEY_VAULT_SERVICE_V1_ALIAS.equals(
+ rootCertAlias)) {
+ // TODO: allow only whitelisted LSKF usage
+ Log.w(TAG, "Untrusted root certificate is used by recovery agent "
+ + recoveryAgentUid);
+ }
+
byte[] salt = generateSalt();
byte[] localLskfHash = hashCredentials(salt, mCredential);
@@ -225,6 +239,8 @@
return;
}
+ // TODO: filter raw keys based on the root of trust.
+ // It is the only place in the class where raw key material is used.
SecretKey recoveryKey;
try {
recoveryKey = generateRecoveryKey();
@@ -451,4 +467,14 @@
}
return keyEntries;
}
+
+ private @NonNull String replaceEmptyValueWithSecureDefault(
+ @Nullable String rootCertificateAlias) {
+ if (rootCertificateAlias == null || rootCertificateAlias.isEmpty()) {
+ Log.e(TAG, "rootCertificateAlias is null or empty");
+ // Use the default Google Key Vault Service CA certificate if the alias is not provided
+ rootCertificateAlias = TrustedRootCertificates.GOOGLE_CLOUD_KEY_VAULT_SERVICE_V1_ALIAS;
+ }
+ return rootCertificateAlias;
+ }
}
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index e0487ea..30125f8 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -176,6 +176,20 @@
checkRecoverKeyStorePermission();
int userId = UserHandle.getCallingUserId();
int uid = Binder.getCallingUid();
+ rootCertificateAlias = replaceEmptyValueWithSecureDefault(rootCertificateAlias);
+
+ // Always set active alias to the argument of the last call to initRecoveryService method,
+ // even if cert file is incorrect.
+ String activeRootAlias = mDatabase.getActiveRootOfTrust(userId, uid);
+ if (activeRootAlias == null) {
+ Log.d(TAG, "Root of trust for recovery agent + " + uid
+ + " is assigned for the first time to " + rootCertificateAlias);
+ mDatabase.setActiveRootOfTrust(userId, uid, rootCertificateAlias);
+ } else if (!activeRootAlias.equals(rootCertificateAlias)) {
+ Log.i(TAG, "Root of trust for recovery agent " + uid + " is changed to "
+ + rootCertificateAlias + " from " + activeRootAlias);
+ mDatabase.setActiveRootOfTrust(userId, uid, rootCertificateAlias);
+ }
CertXml certXml;
try {
@@ -194,7 +208,7 @@
// Check serial number
long newSerial = certXml.getSerial();
- Long oldSerial = mDatabase.getRecoveryServiceCertSerial(userId, uid);
+ Long oldSerial = mDatabase.getRecoveryServiceCertSerial(userId, uid, rootCertificateAlias);
if (oldSerial != null && oldSerial >= newSerial) {
if (oldSerial == newSerial) {
Log.i(TAG, "The cert file serial number is the same, so skip updating.");
@@ -217,12 +231,20 @@
ERROR_INVALID_CERTIFICATE, "Failed to validate certificate.");
}
+ boolean wasInitialized = mDatabase.getRecoveryServiceCertPath(userId, uid,
+ rootCertificateAlias) != null;
+
// Save the chosen and validated certificate into database
try {
Log.d(TAG, "Saving the randomly chosen endpoint certificate to database");
- if (mDatabase.setRecoveryServiceCertPath(userId, uid, certPath) > 0) {
- mDatabase.setRecoveryServiceCertSerial(userId, uid, newSerial);
- mDatabase.setShouldCreateSnapshot(userId, uid, true);
+ if (mDatabase.setRecoveryServiceCertPath(userId, uid, rootCertificateAlias,
+ certPath) > 0) {
+ mDatabase.setRecoveryServiceCertSerial(userId, uid, rootCertificateAlias,
+ newSerial);
+ if (wasInitialized) {
+ Log.i(TAG, "This is a certificate change. Snapshot pending.");
+ mDatabase.setShouldCreateSnapshot(userId, uid, true);
+ }
mDatabase.setCounterId(userId, uid, new SecureRandom().nextLong());
}
} catch (CertificateEncodingException e) {
@@ -248,9 +270,7 @@
@NonNull byte[] recoveryServiceSigFile)
throws RemoteException {
checkRecoverKeyStorePermission();
- if (rootCertificateAlias == null) {
- Log.e(TAG, "rootCertificateAlias is null");
- }
+ rootCertificateAlias = replaceEmptyValueWithSecureDefault(rootCertificateAlias);
Preconditions.checkNotNull(recoveryServiceCertFile, "recoveryServiceCertFile is null");
Preconditions.checkNotNull(recoveryServiceSigFile, "recoveryServiceSigFile is null");
@@ -504,9 +524,7 @@
@NonNull List<KeyChainProtectionParams> secrets)
throws RemoteException {
checkRecoverKeyStorePermission();
- if (rootCertificateAlias == null) {
- Log.e(TAG, "rootCertificateAlias is null");
- }
+ rootCertificateAlias = replaceEmptyValueWithSecureDefault(rootCertificateAlias);
Preconditions.checkNotNull(sessionId, "invalid session");
Preconditions.checkNotNull(verifierCertPath, "verifierCertPath is null");
Preconditions.checkNotNull(vaultParams, "vaultParams is null");
@@ -948,11 +966,7 @@
}
private X509Certificate getRootCertificate(String rootCertificateAlias) throws RemoteException {
- if (rootCertificateAlias == null || rootCertificateAlias.isEmpty()) {
- // Use the default Google Key Vault Service CA certificate if the alias is not provided
- rootCertificateAlias = TrustedRootCertificates.GOOGLE_CLOUD_KEY_VAULT_SERVICE_V1_ALIAS;
- }
-
+ rootCertificateAlias = replaceEmptyValueWithSecureDefault(rootCertificateAlias);
X509Certificate rootCertificate =
TrustedRootCertificates.getRootCertificate(rootCertificateAlias);
if (rootCertificate == null) {
@@ -962,6 +976,16 @@
return rootCertificate;
}
+ private @NonNull String replaceEmptyValueWithSecureDefault(
+ @Nullable String rootCertificateAlias) {
+ if (rootCertificateAlias == null || rootCertificateAlias.isEmpty()) {
+ Log.e(TAG, "rootCertificateAlias is null or empty");
+ // Use the default Google Key Vault Service CA certificate if the alias is not provided
+ rootCertificateAlias = TrustedRootCertificates.GOOGLE_CLOUD_KEY_VAULT_SERVICE_V1_ALIAS;
+ }
+ return rootCertificateAlias;
+ }
+
private void checkRecoverKeyStorePermission() {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.RECOVER_KEYSTORE,
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
index 2676ee8..38834ac 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
@@ -29,6 +29,7 @@
import com.android.server.locksettings.recoverablekeystore.WrappedKey;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.KeysEntry;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServiceMetadataEntry;
+import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RootOfTrustEntry;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.UserMetadataEntry;
import java.io.ByteArrayInputStream;
@@ -385,13 +386,15 @@
*
* @param userId The userId of the profile the application is running under.
* @param uid The uid of the application who initializes the local recovery components.
+ * @param rootAlias The root of trust alias.
* @return The value that were previously set, or null if there's none.
*
* @hide
*/
@Nullable
- public Long getRecoveryServiceCertSerial(int userId, int uid) {
- return getLong(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL);
+ public Long getRecoveryServiceCertSerial(int userId, int uid, @NonNull String rootAlias) {
+ return getLong(userId, uid, rootAlias,
+ RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL);
}
/**
@@ -399,13 +402,16 @@
*
* @param userId The userId of the profile the application is running under.
* @param uid The uid of the application who initializes the local recovery components.
+ * @param rootAlias The root of trust alias.
* @param serial The serial number contained in the XML file for recovery service certificates.
* @return The primary key of the inserted row, or -1 if failed.
*
* @hide
*/
- public long setRecoveryServiceCertSerial(int userId, int uid, long serial) {
- return setLong(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL, serial);
+ public long setRecoveryServiceCertSerial(int userId, int uid, @NonNull String rootAlias,
+ long serial) {
+ return setLong(userId, uid, rootAlias, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL,
+ serial);
}
/**
@@ -413,13 +419,15 @@
*
* @param userId The userId of the profile the application is running under.
* @param uid The uid of the application who initializes the local recovery components.
+ * @param rootAlias The root of trust alias.
* @return The value that were previously set, or null if there's none.
*
* @hide
*/
@Nullable
- public CertPath getRecoveryServiceCertPath(int userId, int uid) {
- byte[] bytes = getBytes(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH);
+ public CertPath getRecoveryServiceCertPath(int userId, int uid, @NonNull String rootAlias) {
+ byte[] bytes = getBytes(userId, uid, rootAlias,
+ RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH);
if (bytes == null) {
return null;
}
@@ -440,16 +448,17 @@
*
* @param userId The userId of the profile the application is running under.
* @param uid The uid of the application who initializes the local recovery components.
+ * @param rootAlias The root of trust alias.
* @param certPath The certificate path of the recovery service.
* @return The primary key of the inserted row, or -1 if failed.
* @hide
*/
- public long setRecoveryServiceCertPath(int userId, int uid, CertPath certPath) throws
- CertificateEncodingException {
+ public long setRecoveryServiceCertPath(int userId, int uid, @NonNull String rootAlias,
+ CertPath certPath) throws CertificateEncodingException {
if (certPath.getCertificates().size() == 0) {
throw new CertificateEncodingException("No certificate contained in the cert path.");
}
- return setBytes(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH,
+ return setBytes(userId, uid, rootAlias, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH,
certPath.getEncoded(CERT_PATH_ENCODING));
}
@@ -608,6 +617,85 @@
}
/**
+ * Active root of trust for the recovery agent.
+ *
+ * @param userId The userId of the profile the application is running under.
+ * @param uid The uid of the application.
+ * @param rootAlias The root of trust alias.
+ * @return The primary key of the updated row, or -1 if failed.
+ *
+ * @hide
+ */
+ public long setActiveRootOfTrust(int userId, int uid, @Nullable String rootAlias) {
+ SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_ACTIVE_ROOT_OF_TRUST, rootAlias);
+ String selection =
+ RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " = ? AND "
+ + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + " = ?";
+ ensureRecoveryServiceMetadataEntryExists(userId, uid);
+ return db.update(RecoveryServiceMetadataEntry.TABLE_NAME, values,
+ selection, new String[] {String.valueOf(userId), String.valueOf(uid)});
+ }
+
+ /**
+ * Active root of trust for the recovery agent.
+ *
+ * @param userId The userId of the profile the application is running under.
+ * @param uid The uid of the application who initialized the local recovery components.
+ * @return Active root of trust alias of null if it was not set
+ *
+ * @hide
+ */
+ public @Nullable String getActiveRootOfTrust(int userId, int uid) {
+ SQLiteDatabase db = mKeyStoreDbHelper.getReadableDatabase();
+
+ String[] projection = {
+ RecoveryServiceMetadataEntry._ID,
+ RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID,
+ RecoveryServiceMetadataEntry.COLUMN_NAME_UID,
+ RecoveryServiceMetadataEntry.COLUMN_NAME_ACTIVE_ROOT_OF_TRUST};
+ String selection =
+ RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " = ? AND "
+ + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + " = ?";
+ String[] selectionArguments = {Integer.toString(userId), Integer.toString(uid)};
+
+ try (
+ Cursor cursor = db.query(
+ RecoveryServiceMetadataEntry.TABLE_NAME,
+ projection,
+ selection,
+ selectionArguments,
+ /*groupBy=*/ null,
+ /*having=*/ null,
+ /*orderBy=*/ null)
+ ) {
+ int count = cursor.getCount();
+ if (count == 0) {
+ return null;
+ }
+ if (count > 1) {
+ Log.wtf(TAG,
+ String.format(Locale.US,
+ "%d deviceId entries found for userId=%d uid=%d. "
+ + "Should only ever be 0 or 1.", count, userId, uid));
+ return null;
+ }
+ cursor.moveToFirst();
+ int idx = cursor.getColumnIndexOrThrow(
+ RecoveryServiceMetadataEntry.COLUMN_NAME_ACTIVE_ROOT_OF_TRUST);
+ if (cursor.isNull(idx)) {
+ return null;
+ }
+ String result = cursor.getString(idx);
+ if (TextUtils.isEmpty(result)) {
+ return null;
+ }
+ return result;
+ }
+ }
+
+ /**
* Updates the counterId
*
* @param userId The userId of the profile the application is running under.
@@ -874,7 +962,6 @@
*
* @hide
*/
-
private long setBytes(int userId, int uid, String key, byte[] value) {
SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
@@ -890,6 +977,176 @@
}
/**
+ * Returns given binary value from the database.
+ *
+ * @param userId The userId of the profile the application is running under.
+ * @param uid The uid of the application who initialized the local recovery components.
+ * @param rootAlias The root of trust alias.
+ * @param key from {@code RootOfTrustEntry}
+ * @return The value that were previously set, or null if there's none.
+ *
+ * @hide
+ */
+ private byte[] getBytes(int userId, int uid, String rootAlias, String key) {
+ SQLiteDatabase db = mKeyStoreDbHelper.getReadableDatabase();
+
+ String[] projection = {
+ RootOfTrustEntry._ID,
+ RootOfTrustEntry.COLUMN_NAME_USER_ID,
+ RootOfTrustEntry.COLUMN_NAME_UID,
+ RootOfTrustEntry.COLUMN_NAME_ROOT_ALIAS,
+ key};
+ String selection =
+ RootOfTrustEntry.COLUMN_NAME_USER_ID + " = ? AND "
+ + RootOfTrustEntry.COLUMN_NAME_UID + " = ? AND "
+ + RootOfTrustEntry.COLUMN_NAME_ROOT_ALIAS + " = ?";
+ String[] selectionArguments = {Integer.toString(userId), Integer.toString(uid), rootAlias};
+
+ try (
+ Cursor cursor = db.query(
+ RootOfTrustEntry.TABLE_NAME,
+ projection,
+ selection,
+ selectionArguments,
+ /*groupBy=*/ null,
+ /*having=*/ null,
+ /*orderBy=*/ null)
+ ) {
+ int count = cursor.getCount();
+ if (count == 0) {
+ return null;
+ }
+ if (count > 1) {
+ Log.wtf(TAG,
+ String.format(Locale.US,
+ "%d entries found for userId=%d uid=%d. "
+ + "Should only ever be 0 or 1.", count, userId, uid));
+ return null;
+ }
+ cursor.moveToFirst();
+ int idx = cursor.getColumnIndexOrThrow(key);
+ if (cursor.isNull(idx)) {
+ return null;
+ } else {
+ return cursor.getBlob(idx);
+ }
+ }
+ }
+
+ /**
+ * Sets a binary value in the database.
+ *
+ * @param userId The userId of the profile the application is running under.
+ * @param uid The uid of the application who initialized the local recovery components.
+ * @param rootAlias The root of trust alias.
+ * @param key defined in {@code RootOfTrustEntry}
+ * @param value new value.
+ * @return The primary key of the inserted row, or -1 if failed.
+ *
+ * @hide
+ */
+ private long setBytes(int userId, int uid, String rootAlias, String key, byte[] value) {
+ SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(key, value);
+ String selection =
+ RootOfTrustEntry.COLUMN_NAME_USER_ID + " = ? AND "
+ + RootOfTrustEntry.COLUMN_NAME_UID + " = ? AND "
+ + RootOfTrustEntry.COLUMN_NAME_ROOT_ALIAS + " = ?";
+ String[] selectionArguments = {Integer.toString(userId), Integer.toString(uid), rootAlias};
+
+ ensureRootOfTrustEntryExists(userId, uid, rootAlias);
+ return db.update(
+ RootOfTrustEntry.TABLE_NAME, values, selection, selectionArguments);
+ }
+
+ /**
+ * Returns given long value from the database.
+ *
+ * @param userId The userId of the profile the application is running under.
+ * @param uid The uid of the application who initialized the local recovery components.
+ * @param rootAlias The root of trust alias.
+ * @param key from {@code RootOfTrustEntry}
+ * @return The value that were previously set, or null if there's none.
+ *
+ * @hide
+ */
+ private Long getLong(int userId, int uid, String rootAlias, String key) {
+ SQLiteDatabase db = mKeyStoreDbHelper.getReadableDatabase();
+
+ String[] projection = {
+ RootOfTrustEntry._ID,
+ RootOfTrustEntry.COLUMN_NAME_USER_ID,
+ RootOfTrustEntry.COLUMN_NAME_UID,
+ RootOfTrustEntry.COLUMN_NAME_ROOT_ALIAS,
+ key};
+ String selection =
+ RootOfTrustEntry.COLUMN_NAME_USER_ID + " = ? AND "
+ + RootOfTrustEntry.COLUMN_NAME_UID + " = ? AND "
+ + RootOfTrustEntry.COLUMN_NAME_ROOT_ALIAS + " = ?";
+ String[] selectionArguments = {Integer.toString(userId), Integer.toString(uid), rootAlias};
+
+ try (
+ Cursor cursor = db.query(
+ RootOfTrustEntry.TABLE_NAME,
+ projection,
+ selection,
+ selectionArguments,
+ /*groupBy=*/ null,
+ /*having=*/ null,
+ /*orderBy=*/ null)
+ ) {
+ int count = cursor.getCount();
+ if (count == 0) {
+ return null;
+ }
+ if (count > 1) {
+ Log.wtf(TAG,
+ String.format(Locale.US,
+ "%d entries found for userId=%d uid=%d. "
+ + "Should only ever be 0 or 1.", count, userId, uid));
+ return null;
+ }
+ cursor.moveToFirst();
+ int idx = cursor.getColumnIndexOrThrow(key);
+ if (cursor.isNull(idx)) {
+ return null;
+ } else {
+ return cursor.getLong(idx);
+ }
+ }
+ }
+
+ /**
+ * Sets a long value in the database.
+ *
+ * @param userId The userId of the profile the application is running under.
+ * @param uid The uid of the application who initialized the local recovery components.
+ * @param rootAlias The root of trust alias.
+ * @param key defined in {@code RootOfTrustEntry}
+ * @param value new value.
+ * @return The primary key of the inserted row, or -1 if failed.
+ *
+ * @hide
+ */
+
+ private long setLong(int userId, int uid, String rootAlias, String key, long value) {
+ SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(key, value);
+ String selection =
+ RootOfTrustEntry.COLUMN_NAME_USER_ID + " = ? AND "
+ + RootOfTrustEntry.COLUMN_NAME_UID + " = ? AND "
+ + RootOfTrustEntry.COLUMN_NAME_ROOT_ALIAS + " = ?";
+ String[] selectionArguments = {Integer.toString(userId), Integer.toString(uid), rootAlias};
+
+ ensureRootOfTrustEntryExists(userId, uid, rootAlias);
+ return db.update(
+ RootOfTrustEntry.TABLE_NAME, values, selection, selectionArguments);
+ }
+
+
+ /**
* Creates an empty row in the recovery service metadata table if such a row doesn't exist for
* the given userId and uid, so db.update will succeed.
*/
@@ -903,6 +1160,20 @@
}
/**
+ * Creates an empty row in the root of trust table if such a row doesn't exist for
+ * the given userId and uid, so db.update will succeed.
+ */
+ private void ensureRootOfTrustEntryExists(int userId, int uid, String rootAlias) {
+ SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(RootOfTrustEntry.COLUMN_NAME_USER_ID, userId);
+ values.put(RootOfTrustEntry.COLUMN_NAME_UID, uid);
+ values.put(RootOfTrustEntry.COLUMN_NAME_ROOT_ALIAS, rootAlias);
+ db.insertWithOnConflict(RootOfTrustEntry.TABLE_NAME, /*nullColumnHack=*/ null,
+ values, SQLiteDatabase.CONFLICT_IGNORE);
+ }
+
+ /**
* Closes all open connections to the database.
*/
public void close() {
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java
index 2c3d3ab..1eff2d4 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java
@@ -230,16 +230,19 @@
/**
* The public key of the recovery service.
+ * Deprecated.
*/
static final String COLUMN_NAME_PUBLIC_KEY = "public_key";
/**
* The certificate path of the recovery service.
+ * Deprecated.
*/
static final String COLUMN_NAME_CERT_PATH = "cert_path";
/**
* The serial number contained in the certificate XML file of the recovery service.
+ * Deprecated.
*/
static final String COLUMN_NAME_CERT_SERIAL = "cert_serial";
@@ -257,5 +260,42 @@
* The server parameters of the recovery service.
*/
static final String COLUMN_NAME_SERVER_PARAMS = "server_params";
+
+ /**
+ * Active root of trust
+ */
+ static final String COLUMN_NAME_ACTIVE_ROOT_OF_TRUST = "active_root_of_trust";
+ }
+
+ /**
+ * Table data for given recovery agent and root of trust pair.
+ */
+ static class RootOfTrustEntry implements BaseColumns {
+ static final String TABLE_NAME = "root_of_trust";
+
+ /**
+ * The user id of the profile the application is running under.
+ */
+ static final String COLUMN_NAME_USER_ID = "user_id";
+
+ /**
+ * The uid of the application that initializes the local recovery components.
+ */
+ static final String COLUMN_NAME_UID = "uid";
+
+ /**
+ * Root of trust alias
+ */
+ static final String COLUMN_NAME_ROOT_ALIAS = "root_alias";
+
+ /**
+ * The certificate path of the recovery service.
+ */
+ static final String COLUMN_NAME_CERT_PATH = "cert_path";
+
+ /**
+ * The serial number contained in the certificate XML file of the recovery service.
+ */
+ static final String COLUMN_NAME_CERT_SERIAL = "cert_serial";
}
}
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java
index 8a89f2d..43efe9c 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java
@@ -23,6 +23,7 @@
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.KeysEntry;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServiceMetadataEntry;
+import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RootOfTrustEntry;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.UserMetadataEntry;
/**
@@ -31,7 +32,7 @@
class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper {
private static final String TAG = "RecoverableKeyStoreDbHp";
- static final int DATABASE_VERSION = 3;
+ static final int DATABASE_VERSION = 4;
private static final String DATABASE_NAME = "recoverablekeystore.db";
private static final String SQL_CREATE_KEYS_ENTRY =
@@ -61,6 +62,7 @@
+ RecoveryServiceMetadataEntry.COLUMN_NAME_UID + " INTEGER,"
+ RecoveryServiceMetadataEntry.COLUMN_NAME_SNAPSHOT_VERSION + " INTEGER,"
+ RecoveryServiceMetadataEntry.COLUMN_NAME_SHOULD_CREATE_SNAPSHOT + " INTEGER,"
+ + RecoveryServiceMetadataEntry.COLUMN_NAME_ACTIVE_ROOT_OF_TRUST + " TEXT,"
+ RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY + " BLOB,"
+ RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH + " BLOB,"
+ RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL + " INTEGER,"
@@ -71,6 +73,19 @@
+ RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + ","
+ RecoveryServiceMetadataEntry.COLUMN_NAME_UID + "))";
+ private static final String SQL_CREATE_ROOT_OF_TRUST_ENTRY =
+ "CREATE TABLE " + RootOfTrustEntry.TABLE_NAME + " ("
+ + RootOfTrustEntry._ID + " INTEGER PRIMARY KEY,"
+ + RootOfTrustEntry.COLUMN_NAME_USER_ID + " INTEGER,"
+ + RootOfTrustEntry.COLUMN_NAME_UID + " INTEGER,"
+ + RootOfTrustEntry.COLUMN_NAME_ROOT_ALIAS + " TEST,"
+ + RootOfTrustEntry.COLUMN_NAME_CERT_PATH + " BLOB,"
+ + RootOfTrustEntry.COLUMN_NAME_CERT_SERIAL + " INTEGER,"
+ + "UNIQUE("
+ + RootOfTrustEntry.COLUMN_NAME_USER_ID + ","
+ + RootOfTrustEntry.COLUMN_NAME_UID + ","
+ + RootOfTrustEntry.COLUMN_NAME_ROOT_ALIAS + "))";
+
private static final String SQL_DELETE_KEYS_ENTRY =
"DROP TABLE IF EXISTS " + KeysEntry.TABLE_NAME;
@@ -80,6 +95,9 @@
private static final String SQL_DELETE_RECOVERY_SERVICE_METADATA_ENTRY =
"DROP TABLE IF EXISTS " + RecoveryServiceMetadataEntry.TABLE_NAME;
+ private static final String SQL_DELETE_ROOT_OF_TRUST_ENTRY =
+ "DROP TABLE IF EXISTS " + RootOfTrustEntry.TABLE_NAME;
+
RecoverableKeyStoreDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@@ -89,21 +107,44 @@
db.execSQL(SQL_CREATE_KEYS_ENTRY);
db.execSQL(SQL_CREATE_USER_METADATA_ENTRY);
db.execSQL(SQL_CREATE_RECOVERY_SERVICE_METADATA_ENTRY);
+ db.execSQL(SQL_CREATE_ROOT_OF_TRUST_ENTRY);
+ }
+
+ @Override
+ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ Log.e(TAG, "Recreating recoverablekeystore after unexpected version downgrade.");
+ dropAllKnownTables(db); // Wipe database.
+ onCreate(db);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < 2) {
- db.execSQL(SQL_DELETE_KEYS_ENTRY);
- db.execSQL(SQL_DELETE_USER_METADATA_ENTRY);
- db.execSQL(SQL_DELETE_RECOVERY_SERVICE_METADATA_ENTRY);
+ dropAllKnownTables(db); // Wipe database.
onCreate(db);
return;
}
- if (oldVersion < 3) {
+ if (oldVersion < 3 && newVersion >= 3) {
upgradeDbForVersion3(db);
+ oldVersion = 3;
}
+
+ if (oldVersion < 4 && newVersion >= 4) {
+ upgradeDbForVersion4(db);
+ oldVersion = 4;
+ }
+
+ if (oldVersion != newVersion) {
+ Log.e(TAG, "Failed to update recoverablekeystore database to the most recent version");
+ }
+ }
+
+ private void dropAllKnownTables(SQLiteDatabase db) {
+ db.execSQL(SQL_DELETE_KEYS_ENTRY);
+ db.execSQL(SQL_DELETE_USER_METADATA_ENTRY);
+ db.execSQL(SQL_DELETE_RECOVERY_SERVICE_METADATA_ENTRY);
+ db.execSQL(SQL_DELETE_ROOT_OF_TRUST_ENTRY);
}
private void upgradeDbForVersion3(SQLiteDatabase db) {
@@ -115,6 +156,16 @@
null);
}
+ private void upgradeDbForVersion4(SQLiteDatabase db) {
+ Log.d(TAG, "Updating recoverable keystore database to version 4");
+ // Add new table with two columns for cert path and cert serial number.
+ db.execSQL(SQL_CREATE_ROOT_OF_TRUST_ENTRY);
+ // adds column to store root of trust currently used by the recovery agent
+ addColumnToTable(db, RecoveryServiceMetadataEntry.TABLE_NAME,
+ RecoveryServiceMetadataEntry.COLUMN_NAME_ACTIVE_ROOT_OF_TRUST, "TEXT",
+ /*defaultStr=*/ null);
+ }
+
private static void addColumnToTable(
SQLiteDatabase db, String tableName, String column, String columnType,
String defaultStr) {
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 01f0d74..0eb906d 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -101,6 +101,7 @@
*/
public class MediaSessionService extends SystemService implements Monitor {
private static final String TAG = "MediaSessionService";
+ static final boolean USE_MEDIA2_APIS = false; // TODO: Change this to true when we're ready.
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
// Leave log for key event always.
private static final boolean DEBUG_KEY_EVENT = true;
@@ -508,6 +509,9 @@
}
private void buildMediaSessionService2List() {
+ if (!USE_MEDIA2_APIS) {
+ return;
+ }
if (DEBUG) {
Log.d(TAG, "buildMediaSessionService2List");
}
@@ -1531,6 +1535,9 @@
*/
@Override
public boolean createSession2(Bundle sessionToken) {
+ if (!USE_MEDIA2_APIS) {
+ return false;
+ }
final int uid = Binder.getCallingUid();
final SessionToken2 token = SessionToken2.fromBundle(sessionToken);
if (token == null || token.getUid() != uid) {
@@ -1570,6 +1577,9 @@
*/
@Override
public void destroySession2(Bundle sessionToken) {
+ if (!USE_MEDIA2_APIS) {
+ return;
+ }
final int uid = Binder.getCallingUid();
final SessionToken2 token = SessionToken2.fromBundle(sessionToken);
if (token == null || token.getUid() != uid) {
@@ -1586,6 +1596,9 @@
@Override
public List<Bundle> getSessionTokens(boolean activeSessionOnly,
boolean sessionServiceOnly, String packageName) throws RemoteException {
+ if (!USE_MEDIA2_APIS) {
+ return null;
+ }
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
@@ -1614,6 +1627,9 @@
@Override
public void addSessionTokensListener(ISessionTokensListener listener, int userId,
String packageName) throws RemoteException {
+ if (!USE_MEDIA2_APIS) {
+ return;
+ }
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
@@ -1637,6 +1653,9 @@
@Override
public void removeSessionTokensListener(ISessionTokensListener listener,
String packageName) throws RemoteException {
+ if (!USE_MEDIA2_APIS) {
+ return;
+ }
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index a5f8dc7..2ef754e 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -16,9 +16,9 @@
package com.android.server.net;
-import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
+import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.METERED_NO;
import static android.net.NetworkStats.METERED_YES;
import static android.net.NetworkStats.ROAMING_NO;
@@ -42,9 +42,11 @@
import android.service.NetworkStatsCollectionProto;
import android.service.NetworkStatsCollectionStatsProto;
import android.telephony.SubscriptionPlan;
+import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.IntArray;
+import android.util.MathUtils;
import android.util.Pair;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -245,7 +247,10 @@
+ " is forbidden for caller " + callerUid);
}
- final int bucketEstimate = (int) ((end - start) / mBucketDuration);
+ // 180 days of history should be enough for anyone; if we end up needing
+ // more, we'll dynamically grow the history object.
+ final int bucketEstimate = (int) MathUtils.constrain(((end - start) / mBucketDuration), 0,
+ (180 * DateUtils.DAY_IN_MILLIS) / mBucketDuration);
final NetworkStatsHistory combined = new NetworkStatsHistory(
mBucketDuration, bucketEstimate, fields);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 59cd561..210857e 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -5969,6 +5969,7 @@
}
private boolean isPackageSuspendedForUser(String pkg, int uid) {
+ final long identity = Binder.clearCallingIdentity();
int userId = UserHandle.getUserId(uid);
try {
return mPackageManager.isPackageSuspendedForUser(pkg, userId);
@@ -5977,6 +5978,8 @@
} catch (IllegalArgumentException ex) {
// Package not found.
return false;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
}
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index e315bc5..0774672 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -472,10 +472,17 @@
if (params.getJobId() == JOB_POST_BOOT_UPDATE) {
mAbortPostBootUpdate.set(true);
+
+ // Do not reschedule.
+ // TODO: We should reschedule if we didn't process all apps, yet.
+ return false;
} else {
mAbortIdleOptimization.set(true);
+
+ // Reschedule the run.
+ // TODO: Should this be dependent on the stop reason?
+ return true;
}
- return false;
}
private void notifyPinService(ArraySet<String> updatedPackages) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 5a63f29..775fdaa 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -92,6 +92,7 @@
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
+import static com.android.internal.util.ArrayUtils.appendElement;
import static com.android.internal.util.ArrayUtils.appendInt;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
@@ -778,8 +779,14 @@
return PackageManagerService.this.hasSystemFeature(feature, 0);
}
- final List<PackageParser.Package> getStaticOverlayPackagesLocked(
+ final List<PackageParser.Package> getStaticOverlayPackages(
Collection<PackageParser.Package> allPackages, String targetPackageName) {
+ if ("android".equals(targetPackageName)) {
+ // Static RROs targeting to "android", ie framework-res.apk, are already applied by
+ // native AssetManager.
+ return null;
+ }
+
List<PackageParser.Package> overlayPackages = null;
for (PackageParser.Package p : allPackages) {
if (targetPackageName.equals(p.mOverlayTarget) && p.mOverlayIsStatic) {
@@ -800,16 +807,8 @@
return overlayPackages;
}
- @GuardedBy("mInstallLock")
- final String[] getStaticOverlayPathsLocked(Collection<PackageParser.Package> allPackages,
- String targetPackageName, String targetPath) {
- if ("android".equals(targetPackageName)) {
- // Static RROs targeting to "android", ie framework-res.apk, are already applied by
- // native AssetManager.
- return null;
- }
- List<PackageParser.Package> overlayPackages =
- getStaticOverlayPackagesLocked(allPackages, targetPackageName);
+ final String[] getStaticOverlayPaths(List<PackageParser.Package> overlayPackages,
+ String targetPath) {
if (overlayPackages == null || overlayPackages.isEmpty()) {
return null;
}
@@ -829,9 +828,11 @@
//
// OverlayManagerService will update each of them with a correct gid from its
// target package app id.
- mInstaller.idmap(targetPath, overlayPackage.baseCodePath,
- UserHandle.getSharedAppGid(
- UserHandle.getUserGid(UserHandle.USER_SYSTEM)));
+ synchronized (mInstallLock) {
+ mInstaller.idmap(targetPath, overlayPackage.baseCodePath,
+ UserHandle.getSharedAppGid(
+ UserHandle.getUserGid(UserHandle.USER_SYSTEM)));
+ }
if (overlayPathList == null) {
overlayPathList = new ArrayList<String>();
}
@@ -845,10 +846,14 @@
}
String[] getStaticOverlayPaths(String targetPackageName, String targetPath) {
+ List<PackageParser.Package> overlayPackages;
synchronized (mPackages) {
- return getStaticOverlayPathsLocked(
- mPackages.values(), targetPackageName, targetPath);
+ overlayPackages = getStaticOverlayPackages(
+ mPackages.values(), targetPackageName);
}
+ // It is safe to keep overlayPackages without holding mPackages because static overlay
+ // packages can't be uninstalled or disabled.
+ return getStaticOverlayPaths(overlayPackages, targetPath);
}
@Override public final String[] getOverlayApks(String targetPackageName) {
@@ -883,7 +888,9 @@
// can't happen while running parallel parsing.
// Moreover holding mPackages on each parsing thread causes dead-lock.
return mOverlayPackages == null ? null :
- getStaticOverlayPathsLocked(mOverlayPackages, targetPackageName, targetPath);
+ getStaticOverlayPaths(
+ getStaticOverlayPackages(mOverlayPackages, targetPackageName),
+ targetPath);
}
}
@@ -13987,18 +13994,15 @@
return packageNames;
}
- // List of package names for whom the suspended state has changed.
- final List<String> changedPackages = new ArrayList<>(packageNames.length);
- // List of package names for whom the suspended state is not set as requested in this
- // method.
+ final List<String> changedPackagesList = new ArrayList<>(packageNames.length);
final List<String> unactionedPackages = new ArrayList<>(packageNames.length);
final long callingId = Binder.clearCallingIdentity();
try {
synchronized (mPackages) {
for (int i = 0; i < packageNames.length; i++) {
final String packageName = packageNames[i];
- if (packageName == callingPackage) {
- Slog.w(TAG, "Calling package: " + callingPackage + "trying to "
+ if (callingPackage.equals(packageName)) {
+ Slog.w(TAG, "Calling package: " + callingPackage + " trying to "
+ (suspended ? "" : "un") + "suspend itself. Ignoring");
unactionedPackages.add(packageName);
continue;
@@ -14018,17 +14022,18 @@
}
pkgSetting.setSuspended(suspended, callingPackage, appExtras,
launcherExtras, userId);
- changedPackages.add(packageName);
+ changedPackagesList.add(packageName);
}
}
}
} finally {
Binder.restoreCallingIdentity(callingId);
}
- // TODO (b/75036698): Also send each package a broadcast when suspended state changed
- if (!changedPackages.isEmpty()) {
- sendPackagesSuspendedForUser(changedPackages.toArray(
- new String[changedPackages.size()]), userId, suspended);
+ if (!changedPackagesList.isEmpty()) {
+ final String[] changedPackages = changedPackagesList.toArray(
+ new String[changedPackagesList.size()]);
+ sendPackagesSuspendedForUser(changedPackages, userId, suspended);
+ sendMyPackageSuspendedOrUnsuspended(changedPackages, suspended, appExtras, userId);
synchronized (mPackages) {
scheduleWritePackageRestrictionsLocked(userId);
}
@@ -14038,7 +14043,7 @@
}
@Override
- public PersistableBundle getPackageSuspendedAppExtras(String packageName, int userId) {
+ public PersistableBundle getSuspendedPackageAppExtras(String packageName, int userId) {
final int callingUid = Binder.getCallingUid();
if (getPackageUid(packageName, 0, userId) != callingUid) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS, null);
@@ -14049,7 +14054,10 @@
throw new IllegalArgumentException("Unknown target package: " + packageName);
}
final PackageUserState packageUserState = ps.readUserState(userId);
- return packageUserState.suspended ? packageUserState.suspendedAppExtras : null;
+ if (packageUserState.suspended) {
+ return packageUserState.suspendedAppExtras;
+ }
+ return null;
}
}
@@ -14065,12 +14073,49 @@
}
final PackageUserState packageUserState = ps.readUserState(userId);
if (packageUserState.suspended) {
- // TODO (b/75036698): Also send this package a broadcast with the new app extras
packageUserState.suspendedAppExtras = appExtras;
+ sendMyPackageSuspendedOrUnsuspended(new String[] {packageName}, true, appExtras,
+ userId);
}
}
}
+ private void sendMyPackageSuspendedOrUnsuspended(String[] affectedPackages, boolean suspended,
+ PersistableBundle appExtras, int userId) {
+ final String action;
+ final Bundle intentExtras = new Bundle();
+ if (suspended) {
+ action = Intent.ACTION_MY_PACKAGE_SUSPENDED;
+ if (appExtras != null) {
+ final Bundle bundledAppExtras = new Bundle(appExtras.deepCopy());
+ intentExtras.putBundle(Intent.EXTRA_SUSPENDED_PACKAGE_EXTRAS, bundledAppExtras);
+ }
+ } else {
+ action = Intent.ACTION_MY_PACKAGE_UNSUSPENDED;
+ }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ final IActivityManager am = ActivityManager.getService();
+ if (am == null) {
+ Slog.wtf(TAG, "IActivityManager null. Cannot send MY_PACKAGE_ "
+ + (suspended ? "" : "UN") + "SUSPENDED broadcasts");
+ return;
+ }
+ final int[] targetUserIds = new int[] {userId};
+ for (String packageName : affectedPackages) {
+ doSendBroadcast(am, action, null, intentExtras,
+ Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, packageName, null,
+ targetUserIds, false);
+ }
+ } catch (RemoteException ex) {
+ // Shouldn't happen as AMS is in the same process.
+ }
+ }
+ });
+ }
+
@Override
public boolean isPackageSuspendedForUser(String packageName, int userId) {
final int callingUid = Binder.getCallingUid();
@@ -18890,7 +18935,7 @@
return true;
}
- private static final class ClearStorageConnection implements ServiceConnection {
+ private final class ClearStorageConnection implements ServiceConnection {
IMediaContainerService mContainerService;
@Override
@@ -21611,37 +21656,35 @@
// the given package is involved with.
if (dumpState.onTitlePrinted()) pw.println();
- try (final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120)) {
- ipw.println();
- ipw.println("Frozen packages:");
- ipw.increaseIndent();
- if (mFrozenPackages.size() == 0) {
- ipw.println("(none)");
- } else {
- for (int i = 0; i < mFrozenPackages.size(); i++) {
- ipw.println(mFrozenPackages.valueAt(i));
- }
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
+ ipw.println();
+ ipw.println("Frozen packages:");
+ ipw.increaseIndent();
+ if (mFrozenPackages.size() == 0) {
+ ipw.println("(none)");
+ } else {
+ for (int i = 0; i < mFrozenPackages.size(); i++) {
+ ipw.println(mFrozenPackages.valueAt(i));
}
- ipw.decreaseIndent();
}
+ ipw.decreaseIndent();
}
if (!checkin && dumpState.isDumping(DumpState.DUMP_VOLUMES) && packageName == null) {
if (dumpState.onTitlePrinted()) pw.println();
- try (final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120)) {
- ipw.println();
- ipw.println("Loaded volumes:");
- ipw.increaseIndent();
- if (mLoadedVolumes.size() == 0) {
- ipw.println("(none)");
- } else {
- for (int i = 0; i < mLoadedVolumes.size(); i++) {
- ipw.println(mLoadedVolumes.valueAt(i));
- }
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
+ ipw.println();
+ ipw.println("Loaded volumes:");
+ ipw.increaseIndent();
+ if (mLoadedVolumes.size() == 0) {
+ ipw.println("(none)");
+ } else {
+ for (int i = 0; i < mLoadedVolumes.size(); i++) {
+ ipw.println(mLoadedVolumes.valueAt(i));
}
- ipw.decreaseIndent();
}
+ ipw.decreaseIndent();
}
if (!checkin && dumpState.isDumping(DumpState.DUMP_SERVICE_PERMISSIONS)
@@ -21770,63 +21813,61 @@
}
private void dumpDexoptStateLPr(PrintWriter pw, String packageName) {
- try (final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ")) {
- ipw.println();
- ipw.println("Dexopt state:");
- ipw.increaseIndent();
- Collection<PackageParser.Package> packages = null;
- if (packageName != null) {
- PackageParser.Package targetPackage = mPackages.get(packageName);
- if (targetPackage != null) {
- packages = Collections.singletonList(targetPackage);
- } else {
- ipw.println("Unable to find package: " + packageName);
- return;
- }
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ ipw.println();
+ ipw.println("Dexopt state:");
+ ipw.increaseIndent();
+ Collection<PackageParser.Package> packages = null;
+ if (packageName != null) {
+ PackageParser.Package targetPackage = mPackages.get(packageName);
+ if (targetPackage != null) {
+ packages = Collections.singletonList(targetPackage);
} else {
- packages = mPackages.values();
+ ipw.println("Unable to find package: " + packageName);
+ return;
}
+ } else {
+ packages = mPackages.values();
+ }
- for (PackageParser.Package pkg : packages) {
- ipw.println("[" + pkg.packageName + "]");
- ipw.increaseIndent();
- mPackageDexOptimizer.dumpDexoptState(ipw, pkg,
- mDexManager.getPackageUseInfoOrDefault(pkg.packageName));
- ipw.decreaseIndent();
- }
+ for (PackageParser.Package pkg : packages) {
+ ipw.println("[" + pkg.packageName + "]");
+ ipw.increaseIndent();
+ mPackageDexOptimizer.dumpDexoptState(ipw, pkg,
+ mDexManager.getPackageUseInfoOrDefault(pkg.packageName));
+ ipw.decreaseIndent();
}
}
private void dumpCompilerStatsLPr(PrintWriter pw, String packageName) {
- try (final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ")) {
- ipw.println();
- ipw.println("Compiler stats:");
- ipw.increaseIndent();
- Collection<PackageParser.Package> packages = null;
- if (packageName != null) {
- PackageParser.Package targetPackage = mPackages.get(packageName);
- if (targetPackage != null) {
- packages = Collections.singletonList(targetPackage);
- } else {
- ipw.println("Unable to find package: " + packageName);
- return;
- }
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ ipw.println();
+ ipw.println("Compiler stats:");
+ ipw.increaseIndent();
+ Collection<PackageParser.Package> packages = null;
+ if (packageName != null) {
+ PackageParser.Package targetPackage = mPackages.get(packageName);
+ if (targetPackage != null) {
+ packages = Collections.singletonList(targetPackage);
} else {
- packages = mPackages.values();
+ ipw.println("Unable to find package: " + packageName);
+ return;
}
+ } else {
+ packages = mPackages.values();
+ }
- for (PackageParser.Package pkg : packages) {
- ipw.println("[" + pkg.packageName + "]");
- ipw.increaseIndent();
+ for (PackageParser.Package pkg : packages) {
+ ipw.println("[" + pkg.packageName + "]");
+ ipw.increaseIndent();
- CompilerStats.PackageStats stats = getCompilerPackageStats(pkg.packageName);
- if (stats == null) {
- ipw.println("(No recorded stats)");
- } else {
- stats.dump(ipw);
- }
- ipw.decreaseIndent();
+ CompilerStats.PackageStats stats = getCompilerPackageStats(pkg.packageName);
+ if (stats == null) {
+ ipw.println("(No recorded stats)");
+ } else {
+ stats.dump(ipw);
}
+ ipw.decreaseIndent();
}
}
@@ -24053,6 +24094,33 @@
}
}
+ @Override
+ public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) {
+ enforceSystemOrPhoneCaller("grantDefaultPermissionsToActiveLuiApp");
+ synchronized (mPackages) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mDefaultPermissionPolicy.grantDefaultPermissionsToActiveLuiApp(
+ packageName, userId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ @Override
+ public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) {
+ enforceSystemOrPhoneCaller("revokeDefaultPermissionsFromLuiApps");
+ synchronized (mPackages) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mDefaultPermissionPolicy.revokeDefaultPermissionsFromLuiApps(packageNames, userId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
private static void enforceSystemOrPhoneCaller(String tag) {
int callingUid = Binder.getCallingUid();
if (callingUid != Process.PHONE_UID && callingUid != Process.SYSTEM_UID) {
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 3116480..518d464 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -972,6 +972,7 @@
grantRuntimePermissions(imsServicePackage, MICROPHONE_PERMISSIONS, userId);
grantRuntimePermissions(imsServicePackage, LOCATION_PERMISSIONS, userId);
grantRuntimePermissions(imsServicePackage, CAMERA_PERMISSIONS, userId);
+ grantRuntimePermissions(imsServicePackage, CONTACTS_PERMISSIONS, userId);
}
}
}
@@ -1010,6 +1011,32 @@
}
}
+ public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) {
+ Log.i(TAG, "Granting permissions to active LUI app for user:" + userId);
+ if (packageName == null) {
+ return;
+ }
+ PackageParser.Package luiAppPackage = getSystemPackage(packageName);
+ if (luiAppPackage != null
+ && doesPackageSupportRuntimePermissions(luiAppPackage)) {
+ grantRuntimePermissions(luiAppPackage, CAMERA_PERMISSIONS, true, userId);
+ }
+ }
+
+ public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) {
+ Log.i(TAG, "Revoke permissions from LUI apps for user:" + userId);
+ if (packageNames == null) {
+ return;
+ }
+ for (String packageName : packageNames) {
+ PackageParser.Package luiAppPackage = getSystemPackage(packageName);
+ if (luiAppPackage != null
+ && doesPackageSupportRuntimePermissions(luiAppPackage)) {
+ revokeRuntimePermissions(luiAppPackage, CAMERA_PERMISSIONS, true, userId);
+ }
+ }
+ }
+
public void grantDefaultPermissionsToDefaultBrowser(String packageName, int userId) {
Log.i(TAG, "Granting permissions to default browser for user:" + userId);
if (packageName == null) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 4dc68ac..2e6e348 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3027,7 +3027,7 @@
// Show IME over the keyguard if the target allows it
boolean allowWhenLocked = (win.isInputMethodWindow() || imeTarget == this)
- && showImeOverKeyguard;;
+ && showImeOverKeyguard;
if (isKeyguardLocked() && isKeyguardOccluded()) {
// Show SHOW_WHEN_LOCKED windows if Keyguard is occluded.
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 062b154..81a8c55 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -213,7 +213,8 @@
// There are no longer any keyguard windows on secondary displays, so pass
// INVALID_DISPLAY. All that means is that showWhenLocked activities on
// secondary displays now get to show.
- ActivityManager.getService().setLockScreenShown(true, INVALID_DISPLAY);
+ ActivityManager.getService().setLockScreenShown(true /* keyguardShowing */,
+ false /* aodShowing */, INVALID_DISPLAY);
} catch (RemoteException e) {
// Local call.
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 0678d08..8af1101 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -23,7 +23,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Rect;
-import android.hardware.fingerprint.IFingerprintDialogReceiver;
+import android.hardware.biometrics.IBiometricDialogReceiver;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -547,7 +547,7 @@
}
@Override
- public void showFingerprintDialog(Bundle bundle, IFingerprintDialogReceiver receiver) {
+ public void showFingerprintDialog(Bundle bundle, IBiometricDialogReceiver receiver) {
if (mBar != null) {
try {
mBar.showFingerprintDialog(bundle, receiver);
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 8901b04..d123099c 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1428,7 +1428,7 @@
void clearWallpaperLocked(boolean defaultFailed, int which, int userId, IRemoteCallback reply) {
if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
- throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to read");
+ throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to clear");
}
WallpaperData wallpaper = null;
diff --git a/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java b/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java
index ae343da..416469b 100644
--- a/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java
+++ b/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java
@@ -19,6 +19,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
+import java.io.PrintWriter;
import java.util.ArrayList;
/**
@@ -88,4 +89,13 @@
}
mTmpRunnableList.clear();
}
+
+ void dump(PrintWriter pw, String header, String prefix) {
+ if (!mAnimatingTokens.isEmpty() || !mFinishedTokens.isEmpty()) {
+ pw.print(prefix); pw.println(header);
+ prefix = prefix + " ";
+ pw.print(prefix); pw.print("mAnimatingTokens="); pw.println(mAnimatingTokens);
+ pw.print(prefix); pw.print("mFinishedTokens="); pw.println(mFinishedTokens);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 41ae48a..c6f156b 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -34,6 +34,8 @@
import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
+import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_UNSET;
import static android.view.WindowManager.TRANSIT_WALLPAPER_CLOSE;
import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
@@ -114,6 +116,7 @@
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
+import com.android.internal.R;
import com.android.internal.util.DumpUtils.Dump;
import com.android.server.AttributeCache;
import com.android.server.wm.WindowManagerService.H;
@@ -1652,14 +1655,26 @@
+ " Callers=" + Debug.getCallers(3));
}
} else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS && enter) {
-
- a = loadAnimationRes("android", enter
- ? com.android.internal.R.anim.task_open_enter_cross_profile_apps
- : com.android.internal.R.anim.task_open_exit);
+ a = loadAnimationRes("android",
+ com.android.internal.R.anim.task_open_enter_cross_profile_apps);
Slog.v(TAG,
"applyAnimation NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS:"
+ " anim=" + a + " transit=" + appTransitionToString(transit)
- + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3));
+ + " isEntrance=true" + " Callers=" + Debug.getCallers(3));
+ } else if (transit == TRANSIT_TRANSLUCENT_ACTIVITY_OPEN && enter) {
+ a = loadAnimationRes("android",
+ com.android.internal.R.anim.activity_translucent_open_enter);
+ Slog.v(TAG,
+ "applyAnimation TRANSIT_TRANSLUCENT_ACTIVITY_OPEN:"
+ + " anim=" + a + " transit=" + appTransitionToString(transit)
+ + " isEntrance=true" + " Callers=" + Debug.getCallers(3));
+ } else if (transit == TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE && !enter) {
+ a = loadAnimationRes("android",
+ com.android.internal.R.anim.activity_translucent_close_exit);
+ Slog.v(TAG,
+ "applyAnimation TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE:"
+ + " anim=" + a + " transit=" + appTransitionToString(transit)
+ + " isEntrance=false" + " Callers=" + Debug.getCallers(3));
} else {
int animAttr = 0;
switch (transit) {
@@ -2001,6 +2016,12 @@
case TRANSIT_KEYGUARD_UNOCCLUDE: {
return "TRANSIT_KEYGUARD_UNOCCLUDE";
}
+ case TRANSIT_TRANSLUCENT_ACTIVITY_OPEN: {
+ return "TRANSIT_TRANSLUCENT_ACTIVITY_OPEN";
+ }
+ case TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE: {
+ return "TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE";
+ }
default: {
return "<UNKNOWN>";
}
@@ -2173,16 +2194,20 @@
|| transit == TRANSIT_KEYGUARD_UNOCCLUDE;
}
- private static boolean isTaskTransit(int transit) {
- return transit == TRANSIT_TASK_OPEN
+ static boolean isTaskTransit(int transit) {
+ return isTaskOpenTransit(transit)
|| transit == TRANSIT_TASK_CLOSE
- || transit == TRANSIT_TASK_OPEN_BEHIND
|| transit == TRANSIT_TASK_TO_BACK
- || transit == TRANSIT_TASK_TO_FRONT
|| transit == TRANSIT_TASK_IN_PLACE;
}
- private static boolean isActivityTransit(int transit) {
+ private static boolean isTaskOpenTransit(int transit) {
+ return transit == TRANSIT_TASK_OPEN
+ || transit == TRANSIT_TASK_OPEN_BEHIND
+ || transit == TRANSIT_TASK_TO_FRONT;
+ }
+
+ static boolean isActivityTransit(int transit) {
return transit == TRANSIT_ACTIVITY_OPEN
|| transit == TRANSIT_ACTIVITY_CLOSE
|| transit == TRANSIT_ACTIVITY_RELAUNCH;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 85436da..56c9e51 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1660,6 +1660,10 @@
true /* topToBottom */);
}
+ SurfaceControl getAppAnimationLayer() {
+ return getAppAnimationLayer(needsZBoost());
+ }
+
@Override
public SurfaceControl getAnimationLeashParent() {
// All normal app transitions take place in an animation layer which is below the pinned
@@ -1855,7 +1859,7 @@
leash.setLayer(layer);
final DisplayContent dc = getDisplayContent();
- dc.assignStackOrdering(t);
+ dc.assignStackOrdering();
if (mAnimatingAppWindowTokenRegistry != null) {
mAnimatingAppWindowTokenRegistry.notifyStarting(this);
}
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index d000bb6..1f95868 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -110,6 +110,11 @@
SurfaceAnimator mSurfaceAnimator;
/**
+ * Determines whether the dim layer should animate before destroying.
+ */
+ boolean mAnimateExit = true;
+
+ /**
* Used for Dims not associated with a WindowContainer. See {@link Dimmer#dimAbove} for
* details on Dim lifecycle.
*/
@@ -260,6 +265,12 @@
}
}
+ void dontAnimateExit() {
+ if (mDimState != null) {
+ mDimState.mAnimateExit = false;
+ }
+ }
+
/**
* Call after invoking {@link WindowContainer#prepareSurfaces} on children as
* described in {@link #resetDimStates}.
@@ -274,7 +285,11 @@
}
if (!mDimState.mDimming) {
- startDimExit(mLastRequestedDimContainer, mDimState.mSurfaceAnimator, t);
+ if (!mDimState.mAnimateExit) {
+ t.destroy(mDimState.mDimLayer);
+ } else {
+ startDimExit(mLastRequestedDimContainer, mDimState.mSurfaceAnimator, t);
+ }
mDimState = null;
return false;
} else {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index a7eac55..2ffdbfd 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3180,6 +3180,7 @@
* A control placed at the appropriate level for transitions to occur.
*/
SurfaceControl mAppAnimationLayer = null;
+ SurfaceControl mBoostedAppAnimationLayer = null;
/**
* Given that the split-screen divider does not have an AppWindowToken, it
@@ -3531,12 +3532,14 @@
}
void assignStackOrdering(SurfaceControl.Transaction t) {
+
final int HOME_STACK_STATE = 0;
final int NORMAL_STACK_STATE = 1;
final int ALWAYS_ON_TOP_STATE = 2;
int layer = 0;
int layerForAnimationLayer = 0;
+ int layerForBoostedAnimationLayer = 0;
for (int state = 0; state <= ALWAYS_ON_TOP_STATE; state++) {
for (int i = 0; i < mChildren.size(); i++) {
@@ -3558,16 +3561,22 @@
// highest animating stack and no higher.
layerForAnimationLayer = layer++;
}
+ if (state != ALWAYS_ON_TOP_STATE) {
+ layerForBoostedAnimationLayer = layer++;
+ }
}
}
if (mAppAnimationLayer != null) {
t.setLayer(mAppAnimationLayer, layerForAnimationLayer);
}
+ if (mBoostedAppAnimationLayer != null) {
+ t.setLayer(mBoostedAppAnimationLayer, layerForBoostedAnimationLayer);
+ }
}
@Override
- SurfaceControl getAppAnimationLayer() {
- return mAppAnimationLayer;
+ SurfaceControl getAppAnimationLayer(boolean boosted) {
+ return boosted ? mBoostedAppAnimationLayer : mAppAnimationLayer;
}
SurfaceControl getSplitScreenDividerAnchor() {
@@ -3581,16 +3590,22 @@
mAppAnimationLayer = makeChildSurface(null)
.setName("animationLayer")
.build();
+ mBoostedAppAnimationLayer = makeChildSurface(null)
+ .setName("boostedAnimationLayer")
+ .build();
mSplitScreenDividerAnchor = makeChildSurface(null)
.setName("splitScreenDividerAnchor")
.build();
getPendingTransaction()
.show(mAppAnimationLayer)
+ .show(mBoostedAppAnimationLayer)
.show(mSplitScreenDividerAnchor);
scheduleAnimation();
} else {
mAppAnimationLayer.destroy();
mAppAnimationLayer = null;
+ mBoostedAppAnimationLayer.destroy();
+ mBoostedAppAnimationLayer = null;
mSplitScreenDividerAnchor.destroy();
mSplitScreenDividerAnchor = null;
}
@@ -3872,7 +3887,7 @@
super.prepareSurfaces();
}
- void assignStackOrdering(SurfaceControl.Transaction t) {
- mTaskStackContainers.assignStackOrdering(t);
+ void assignStackOrdering() {
+ mTaskStackContainers.assignStackOrdering(getPendingTransaction());
}
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 87a7a74..1018848 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -41,7 +41,6 @@
import android.util.Slog;import android.util.proto.ProtoOutputStream;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
-import android.util.proto.ProtoOutputStream;
import android.view.IRecentsAnimationController;
import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationTarget;
@@ -309,12 +308,15 @@
mCallbacks.onAnimationFinished(false /* moveHomeToTop */);
}
- void cleanupAnimation() {
+ void cleanupAnimation(boolean moveHomeToTop) {
if (DEBUG) Log.d(TAG, "cleanupAnimation(): mPendingAnimations="
+ mPendingAnimations.size());
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
final TaskAnimationAdapter adapter = mPendingAnimations.get(i);
adapter.mTask.setCanAffectSystemUiFlags(true);
+ if (moveHomeToTop) {
+ adapter.mTask.dontAnimateDimExit();
+ }
adapter.mCapturedFinishCallback.onAnimationFinished(adapter);
}
mPendingAnimations.clear();
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 3e7feda..379a1a1 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -134,11 +134,18 @@
private RemoteAnimationTarget[] createAnimations() {
final ArrayList<RemoteAnimationTarget> targets = new ArrayList<>();
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ final RemoteAnimationAdapterWrapper wrapper = mPendingAnimations.get(i);
final RemoteAnimationTarget target =
mPendingAnimations.get(i).createRemoteAppAnimation();
if (target != null) {
targets.add(target);
} else {
+
+ // We can't really start an animation but we still need to make sure to finish the
+ // pending animation that was started by SurfaceAnimator
+ if (wrapper.mCapturedFinishCallback != null) {
+ wrapper.mCapturedFinishCallback.onAnimationFinished(wrapper);
+ }
mPendingAnimations.remove(i);
}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index e4722f9..e8d3210 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -645,6 +645,10 @@
return mCanAffectSystemUiFlags;
}
+ void dontAnimateDimExit() {
+ mDimmer.dontAnimateExit();
+ }
+
@Override
public String toString() {
return "{taskId=" + mTaskId + " appTokens=" + mChildren + " mdr=" + mDeferRemoval + "}";
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 900e2df..62754ad 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1387,6 +1387,7 @@
token.dump(pw, " ", dumpAll);
}
}
+ mAnimatingAppWindowTokenRegistry.dump(pw, "AnimatingApps:", prefix);
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 28fdaae..60e7c0d 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1125,12 +1125,15 @@
}
/**
+ * @param boosted If true, returns an animation layer that happens above all {@link TaskStack}s
+ * Otherwise, the layer will be positioned above all animating
+ * {@link TaskStack}s.
* @return The layer on which all app animations are happening.
*/
- SurfaceControl getAppAnimationLayer() {
+ SurfaceControl getAppAnimationLayer(boolean boosted) {
final WindowContainer parent = getParent();
if (parent != null) {
- return parent.getAppAnimationLayer();
+ return parent.getAppAnimationLayer(boosted);
}
return null;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 449aa2c..0b5c006 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2700,10 +2700,10 @@
}
}
- public void cleanupRecentsAnimation() {
+ public void cleanupRecentsAnimation(boolean moveHomeToTop) {
synchronized (mWindowMap) {
if (mRecentsAnimationController != null) {
- mRecentsAnimationController.cleanupAnimation();
+ mRecentsAnimationController.cleanupAnimation(moveHomeToTop);
mRecentsAnimationController = null;
mAppTransition.updateBooster();
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 3256762..b85f4a4 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -16,12 +16,13 @@
package com.android.server.wm;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManagerInternal.APP_TRANSITION_SNAPSHOT;
import static android.app.ActivityManagerInternal.APP_TRANSITION_SPLASH_SCREEN;
import static android.app.ActivityManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
+import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
@@ -42,6 +43,7 @@
import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN;
import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
import static com.android.server.wm.AppTransition.isKeyguardGoingAwayTransit;
+import static com.android.server.wm.AppTransition.isTaskTransit;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
@@ -61,16 +63,15 @@
import android.view.Display;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
-import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.TransitionType;
import android.view.animation.Animation;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.WindowManagerService.H;
import java.io.PrintWriter;
-import java.util.ArrayList;
import java.util.function.Predicate;
/**
@@ -288,6 +289,7 @@
final boolean closingAppHasWallpaper = canBeWallpaperTarget(mService.mClosingApps)
&& hasWallpaperTarget;
+ transit = maybeUpdateTransitToTranslucentAnim(transit);
transit = maybeUpdateTransitToWallpaper(transit, openingAppHasWallpaper,
closingAppHasWallpaper);
@@ -676,8 +678,9 @@
transit = TRANSIT_WALLPAPER_CLOSE;
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit away from wallpaper: "
+ AppTransition.appTransitionToString(transit));
- } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw() &&
- openingApps.contains(wallpaperTarget.mAppToken)) {
+ } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw()
+ && openingApps.contains(wallpaperTarget.mAppToken)
+ && transit != TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE) {
// We are transitioning from an activity without
// a wallpaper to now showing the wallpaper
transit = TRANSIT_WALLPAPER_OPEN;
@@ -688,6 +691,50 @@
return transit;
}
+ /**
+ * There are cases where we open/close a new task/activity, but in reality only a translucent
+ * activity on top of existing activities is opening/closing. For that one, we have a different
+ * animation because non of the task/activity animations actually work well with translucent
+ * apps.
+ *
+ * @param transit The current transition type.
+ * @return The current transition type or
+ * {@link WindowManager#TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE}/
+ * {@link WindowManager#TRANSIT_TRANSLUCENT_ACTIVITY_OPEN} if appropriate for the
+ * situation.
+ */
+ @VisibleForTesting
+ int maybeUpdateTransitToTranslucentAnim(int transit) {
+ final boolean taskOrActivity = AppTransition.isTaskTransit(transit)
+ || AppTransition.isActivityTransit(transit);
+ boolean allOpeningVisible = true;
+ boolean allTranslucentOpeningApps = !mService.mOpeningApps.isEmpty();
+ for (int i = mService.mOpeningApps.size() - 1; i >= 0; i--) {
+ final AppWindowToken token = mService.mOpeningApps.valueAt(i);
+ if (!token.isVisible()) {
+ allOpeningVisible = false;
+ if (token.fillsParent()) {
+ allTranslucentOpeningApps = false;
+ }
+ }
+ }
+ boolean allTranslucentClosingApps = !mService.mClosingApps.isEmpty();
+ for (int i = mService.mClosingApps.size() - 1; i >= 0; i--) {
+ if (mService.mClosingApps.valueAt(i).fillsParent()) {
+ allTranslucentClosingApps = false;
+ break;
+ }
+ }
+
+ if (taskOrActivity && allTranslucentClosingApps && allOpeningVisible) {
+ return TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
+ }
+ if (taskOrActivity && allTranslucentOpeningApps && mService.mClosingApps.isEmpty()) {
+ return TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
+ }
+ return transit;
+ }
+
private boolean canBeWallpaperTarget(ArraySet<AppWindowToken> apps) {
for (int i = apps.size() - 1; i >= 0; i--) {
if (apps.valueAt(i).windowsCanBeWallpaperTarget()) {
diff --git a/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp b/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp
index e9d4482..ccb4f59 100644
--- a/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp
+++ b/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp
@@ -19,6 +19,7 @@
#include "jni.h"
#include <nativehelper/JNIHelp.h>
+#include "android-base/strings.h"
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/Log.h"
@@ -33,24 +34,36 @@
#define DRIVER_NAME "/dev/usb_accessory"
-#define USB_IN_JACK_NAME "USB in Jack"
-#define USB_OUT_JACK_NAME "USB out Jack"
+#define USB_IN_JACK_SUFFIX "Input Jack"
+#define USB_OUT_JACK_SUFFIX "Output Jack"
namespace android
{
-static jboolean is_jack_connected(jint card, const char* control) {
+static struct mixer_ctl* find_mixer_with_suffix(struct mixer* card_mixer, const char* suffix) {
+ int id = 0;
+ struct mixer_ctl* ctl;
+ while ((ctl = mixer_get_ctl(card_mixer, id++)) != NULL) {
+ const char* name = mixer_ctl_get_name(ctl);
+ if (android::base::EndsWith(name, suffix)) {
+ return ctl;
+ }
+ }
+ return NULL;
+}
+
+static jboolean is_jack_connected(jint card, const char* suffix) {
struct mixer* card_mixer = mixer_open(card);
if (card_mixer == NULL) {
return true;
}
- struct mixer_ctl* ctl = mixer_get_ctl_by_name(card_mixer, control);
+ struct mixer_ctl* ctl = find_mixer_with_suffix(card_mixer, suffix);
if (!ctl) {
return true;
}
mixer_ctl_update(ctl);
int val = mixer_ctl_get_value(ctl, 0);
- ALOGI("JACK %s - value %d\n", control, val);
+ ALOGI("%s - value %d\n", mixer_ctl_get_name(ctl), val);
mixer_close(card_mixer);
return val != 0;
@@ -66,33 +79,31 @@
}
jboolean has_jack = false;
- if ((mixer_get_ctl_by_name(card_mixer, USB_IN_JACK_NAME) != NULL) ||
- (mixer_get_ctl_by_name(card_mixer, USB_OUT_JACK_NAME) != NULL)) {
+ if ((find_mixer_with_suffix(card_mixer, USB_IN_JACK_SUFFIX) != NULL) ||
+ (find_mixer_with_suffix(card_mixer, USB_OUT_JACK_SUFFIX) != NULL)) {
has_jack = true;
}
mixer_close(card_mixer);
return has_jack;
}
-
static jboolean android_server_UsbAlsaJackDetector_inputJackConnected(JNIEnv* /* env */,
jobject /* thiz */,
jint card)
{
- return is_jack_connected(card, USB_IN_JACK_NAME);
+ return is_jack_connected(card, USB_IN_JACK_SUFFIX);
}
-
static jboolean android_server_UsbAlsaJackDetector_outputJackConnected(JNIEnv* /* env */,
jobject /* thiz */,
jint card)
{
- return is_jack_connected(card, USB_OUT_JACK_NAME);
+ return is_jack_connected(card, USB_OUT_JACK_SUFFIX);
}
static void android_server_UsbAlsaJackDetector_jackDetect(JNIEnv* env,
- jobject thiz,
- jint card) {
+ jobject thiz,
+ jint card) {
jclass jdclass = env->GetObjectClass(thiz);
jmethodID method_jackDetectCallback = env->GetMethodID(jdclass, "jackDetectCallback", "()Z");
if (method_jackDetectCallback == NULL) {
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index b452ea5..cda968a7 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -240,7 +240,7 @@
doReturn(displayShouldSleep).when(display).shouldSleep();
doReturn(displaySleeping).when(display).isSleeping();
- doReturn(keyguardShowing).when(keyguard).isKeyguardShowing(anyInt());
+ doReturn(keyguardShowing).when(keyguard).isKeyguardOrAodShowing(anyInt());
mSupervisor.mFocusedStack = isFocusedStack ? stack : null;
mSupervisor.applySleepTokensLocked(true);
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 6fdb029..3c10b03 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -389,6 +389,14 @@
sentIntents.add(intent);
return 0;
}
+
+ @Override
+ void reportGlobalUsageEventLocked(int event) {
+ }
+
+ @Override
+ void reportCurWakefulnessUsageEvent() {
+ }
}
private static class TestHandler extends Handler {
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
index d922df3..fb25cf3 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
@@ -85,9 +85,6 @@
255
};
- private static final int[] MINIMUM_BRIGHTNESS_CURVE_LUX = { 2000, 4000 };
- private static final float[] MINIMUM_BRIGHTNESS_CURVE_NITS = { 1.0f, 50.0f, 90.0f };
-
private static final float[] DISPLAY_RANGE_NITS = { 2.685f, 478.5f };
private static final int[] BACKLIGHT_RANGE = { 1, 255 };
@@ -384,19 +381,6 @@
com.android.internal.R.array.config_autoBrightnessDisplayValuesNits))
.thenReturn(mockBrightnessLevelNits);
- int[] mockMinimumBrightnessCurveLux = new int[MINIMUM_BRIGHTNESS_CURVE_LUX.length];
- for (int i = 0; i < mockMinimumBrightnessCurveLux.length; i++) {
- mockMinimumBrightnessCurveLux[i] = (int) MINIMUM_BRIGHTNESS_CURVE_LUX[i];
- }
- when(mockResources.getIntArray(
- com.android.internal.R.array.config_autoBrightnessMinimumBrightnessCurveLux))
- .thenReturn(mockMinimumBrightnessCurveLux);
- TypedArray mockMinimumBrightnessCurveNits = createFloatTypedArray(
- MINIMUM_BRIGHTNESS_CURVE_NITS);
- when(mockResources.obtainTypedArray(
- com.android.internal.R.array.config_autoBrightnessMinimumBrightnessCurveNits))
- .thenReturn(mockMinimumBrightnessCurveNits);
-
TypedArray mockNitsRange = createFloatTypedArray(nitsRange);
when(mockResources.obtainTypedArray(
com.android.internal.R.array.config_screenBrightnessNits))
@@ -435,78 +419,4 @@
return mockArray;
}
- private float[] getNearMinimumNits(float epsilon) {
- float[] lux = new float[MINIMUM_BRIGHTNESS_CURVE_LUX.length + 1];
- for (int i = 0; i < MINIMUM_BRIGHTNESS_CURVE_LUX.length; i++) {
- lux[i+1] = MINIMUM_BRIGHTNESS_CURVE_LUX[i];
- }
- Spline minimumBrightnessCurve = Spline.createSpline(lux, MINIMUM_BRIGHTNESS_CURVE_NITS);
- float[] nits = new float[LUX_LEVELS.length];
- for (int i = 0; i < nits.length; i++) {
- nits[i] = minimumBrightnessCurve.interpolate(LUX_LEVELS[i]) + epsilon;
- }
- return nits;
- }
-
- @Test
- public void testCreateWithTooDarkBrightnessConfigurationThrowsException() {
- float[] nits = getNearMinimumNits(-0.1f);
- Resources res = createResources(LUX_LEVELS, nits, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
- Exception thrown = null;
- try {
- BrightnessMappingStrategy.create(res);
- } catch (IllegalArgumentException e) {
- thrown = e;
- }
- assertNotNull("Failed to throw IllegalArgumentException", thrown);
- }
-
- @Test
- public void testCreationWithBrightEnoughBrightnessConfigurationDoesNotThrowException() {
- float[] nits = getNearMinimumNits(0);
- Resources res = createResources(LUX_LEVELS, nits, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
- assertNotNull("Failed to create BrightnessMappingStrategy",
- BrightnessMappingStrategy.create(res));
- }
-
- @Test
- public void testSettingTooDarkBrightnessConfigurationThrowsException() {
- Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS,
- BACKLIGHT_RANGE);
- BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
- assertNotNull("Failed to create BrightnessMappingStrategy", strategy);
- float[] lux = new float[LUX_LEVELS.length];
- for (int i = 0; i < lux.length; i++) {
- lux[i] = LUX_LEVELS[i];
- }
- float[] nits = getNearMinimumNits(-0.1f);
- BrightnessConfiguration config = new BrightnessConfiguration.Builder()
- .setCurve(lux, nits)
- .build();
- Exception thrown = null;
- try {
- strategy.setBrightnessConfiguration(config);
- } catch (IllegalArgumentException e) {
- thrown = e;
- }
- assertNotNull("Failed to throw IllegalArgumentException", thrown);
- }
-
- @Test
- public void testSettingBrightEnouhgBrightnessConfigurationDoesNotThrowException() {
- Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS,
- BACKLIGHT_RANGE);
- BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
- assertNotNull("Failed to create BrightnessMappingStrategy", strategy);
- float[] lux = new float[LUX_LEVELS.length];
- for (int i = 0; i < lux.length; i++) {
- lux[i] = LUX_LEVELS[i];
- }
- float[] nits = getNearMinimumNits(0);
- BrightnessConfiguration config = new BrightnessConfiguration.Builder()
- .setCurve(lux, nits)
- .build();
- assertTrue("failed to set brightness configuration",
- strategy.setBrightnessConfiguration(config));
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index 0ea2317..9ae45ea 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -74,6 +74,7 @@
public class KeySyncTaskTest {
private static final String KEY_ALGORITHM = "AES";
private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore";
+ private static final String TEST_ROOT_CERT_ALIAS = "trusted_root";
private static final String WRAPPING_KEY_ALIAS = "KeySyncTaskTest/WrappingKey";
private static final String DATABASE_FILE_NAME = "recoverablekeystore.db";
private static final int TEST_USER_ID = 1000;
@@ -111,6 +112,11 @@
new int[] {TYPE_LOCKSCREEN});
mRecoverableKeyStoreDb.setRecoverySecretTypes(TEST_USER_ID, TEST_RECOVERY_AGENT_UID2,
new int[] {TYPE_LOCKSCREEN});
+
+ mRecoverableKeyStoreDb.setActiveRootOfTrust(TEST_USER_ID, TEST_RECOVERY_AGENT_UID,
+ TEST_ROOT_CERT_ALIAS);
+ mRecoverableKeyStoreDb.setActiveRootOfTrust(TEST_USER_ID, TEST_RECOVERY_AGENT_UID2,
+ TEST_ROOT_CERT_ALIAS);
mRecoverySnapshotStorage = new RecoverySnapshotStorage();
mKeySyncTask = new KeySyncTask(
@@ -247,7 +253,7 @@
TEST_APP_KEY_ALIAS,
WrappedKey.fromSecretKey(mEncryptKey, applicationKey));
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
mKeySyncTask.run();
@@ -263,7 +269,7 @@
mRecoverableKeyStoreDb.setPlatformKeyGenerationId(TEST_USER_ID, TEST_GENERATION_ID);
addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
mKeySyncTask.run();
@@ -273,7 +279,7 @@
@Test
public void run_sendsEncryptedKeysIfAvailableToSync_withRawPublicKey() throws Exception {
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
mRecoverableKeyStoreDb.setServerParams(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE);
@@ -320,7 +326,7 @@
@Test
public void run_sendsEncryptedKeysIfAvailableToSync_withCertPath() throws Exception {
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
mRecoverableKeyStoreDb.setServerParams(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE);
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
@@ -339,7 +345,7 @@
@Test
public void run_setsCorrectSnapshotVersion() throws Exception {
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
@@ -358,7 +364,7 @@
@Test
public void run_recreatesMissingSnapshot() throws Exception {
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
@@ -388,7 +394,7 @@
mPlatformKeyManager);
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
SecretKey applicationKey =
addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
@@ -414,7 +420,7 @@
mPlatformKeyManager);
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
SecretKey applicationKey =
addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
@@ -441,7 +447,7 @@
mPlatformKeyManager);
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
SecretKey applicationKey =
addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
@@ -457,9 +463,9 @@
@Test
public void run_sendsEncryptedKeysWithTwoRegisteredAgents() throws Exception {
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, TestData.CERT_PATH_1);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID2)).thenReturn(true);
addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
@@ -479,9 +485,9 @@
new int[] {1000});
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, TestData.CERT_PATH_1);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID2)).thenReturn(true);
addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
@@ -496,9 +502,9 @@
@Test
public void run_notifiesNonregisteredAgent() throws Exception {
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, TestData.CERT_PATH_1);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID2)).thenReturn(false);
addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index 06b94cb..f5f5027 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -44,9 +44,10 @@
import android.security.keystore.AndroidKeyStoreSecretKey;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
-import android.security.keystore.recovery.KeyDerivationParams;
import android.security.keystore.recovery.KeyChainProtectionParams;
+import android.security.keystore.recovery.KeyDerivationParams;
import android.security.keystore.recovery.RecoveryCertPath;
+import android.security.keystore.recovery.TrustedRootCertificates;
import android.security.keystore.recovery.WrappedApplicationKey;
import android.support.test.filters.SmallTest;
import android.support.test.InstrumentationRegistry;
@@ -90,6 +91,8 @@
private static final String DATABASE_FILE_NAME = "recoverablekeystore.db";
private static final String ROOT_CERTIFICATE_ALIAS = "";
+ private static final String DEFAULT_ROOT_CERT_ALIAS =
+ TrustedRootCertificates.GOOGLE_CLOUD_KEY_VAULT_SERVICE_V1_ALIAS;
private static final String TEST_SESSION_ID = "karlin";
private static final byte[] TEST_PUBLIC_KEY = new byte[] {
(byte) 0x30, (byte) 0x59, (byte) 0x30, (byte) 0x13, (byte) 0x06, (byte) 0x07, (byte) 0x2a,
@@ -143,7 +146,7 @@
private static final String KEY_ALGORITHM = "AES";
private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore";
private static final String WRAPPING_KEY_ALIAS = "RecoverableKeyStoreManagerTest/WrappingKey";
- private static final String TEST_ROOT_CERT_ALIAS = "";
+ private static final String TEST_DEFAULT_ROOT_CERT_ALIAS = "";
private static final KeyChainProtectionParams TEST_PROTECTION_PARAMS =
new KeyChainProtectionParams.Builder()
.setUserSecretType(TYPE_LOCKSCREEN)
@@ -298,11 +301,11 @@
mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
TestData.getCertXmlWithSerial(certSerial));
- assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
- assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isEqualTo(
- TestData.CERT_PATH_1);
- assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)).isEqualTo(
- certSerial);
+ assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid,
+ DEFAULT_ROOT_CERT_ALIAS)).isEqualTo(TestData.CERT_PATH_1);
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid,
+ DEFAULT_ROOT_CERT_ALIAS)).isEqualTo(certSerial);
assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId, uid)).isNull();
}
@@ -328,7 +331,8 @@
byte[] modifiedCertXml = TestData.getCertXml();
modifiedCertXml[modifiedCertXml.length - 50] ^= 1; // Flip a bit in the certificate
try {
- mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS, modifiedCertXml);
+ mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
+ modifiedCertXml);
fail("should have thrown");
} catch (ServiceSpecificException e) {
assertThat(e.getMessage()).contains("validate cert");
@@ -346,8 +350,9 @@
mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
TestData.getCertXmlWithSerial(certSerial + 1));
- assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid))
- .isEqualTo(certSerial + 1);
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid,
+ DEFAULT_ROOT_CERT_ALIAS)).isEqualTo(certSerial + 1);
+ assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
}
@Test
@@ -361,8 +366,9 @@
mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
TestData.getCertXmlWithSerial(certSerial - 1));
- assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid))
- .isEqualTo(certSerial);
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid,
+ DEFAULT_ROOT_CERT_ALIAS)).isEqualTo(certSerial);
+ assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
}
@Test
@@ -373,7 +379,6 @@
mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
TestData.getCertXmlWithSerial(certSerial));
- mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);
mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
TestData.getCertXmlWithSerial(certSerial));
@@ -390,8 +395,10 @@
mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS, TEST_PUBLIC_KEY);
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
- assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isNull();
- assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)).isNull();
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid,
+ DEFAULT_ROOT_CERT_ALIAS)).isNull();
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid,
+ DEFAULT_ROOT_CERT_ALIAS)).isNull();
assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId, uid)).isNotNull();
}
@@ -404,9 +411,9 @@
mRecoverableKeyStoreManager.initRecoveryServiceWithSigFile(
ROOT_CERTIFICATE_ALIAS, TestData.getCertXml(), TestData.getSigXml());
- assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
- assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isEqualTo(
- TestData.CERT_PATH_1);
+ assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid,
+ DEFAULT_ROOT_CERT_ALIAS)).isEqualTo(TestData.CERT_PATH_1);
assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId, uid)).isNull();
}
@@ -479,7 +486,7 @@
public void startRecoverySessionWithCertPath_storesTheSessionInfo() throws Exception {
mRecoverableKeyStoreManager.startRecoverySessionWithCertPath(
TEST_SESSION_ID,
- TEST_ROOT_CERT_ALIAS,
+ TEST_DEFAULT_ROOT_CERT_ALIAS,
RecoveryCertPath.createRecoveryCertPath(TestData.CERT_PATH_1),
TEST_VAULT_PARAMS,
TEST_VAULT_CHALLENGE,
@@ -496,7 +503,7 @@
public void startRecoverySessionWithCertPath_checksPermissionFirst() throws Exception {
mRecoverableKeyStoreManager.startRecoverySessionWithCertPath(
TEST_SESSION_ID,
- TEST_ROOT_CERT_ALIAS,
+ TEST_DEFAULT_ROOT_CERT_ALIAS,
RecoveryCertPath.createRecoveryCertPath(TestData.CERT_PATH_1),
TEST_VAULT_PARAMS,
TEST_VAULT_CHALLENGE,
@@ -600,7 +607,7 @@
try {
mRecoverableKeyStoreManager.startRecoverySessionWithCertPath(
TEST_SESSION_ID,
- TEST_ROOT_CERT_ALIAS,
+ TEST_DEFAULT_ROOT_CERT_ALIAS,
RecoveryCertPath.createRecoveryCertPath(TestData.CERT_PATH_1),
TEST_VAULT_PARAMS,
TEST_VAULT_CHALLENGE,
@@ -619,7 +626,7 @@
try {
mRecoverableKeyStoreManager.startRecoverySessionWithCertPath(
TEST_SESSION_ID,
- TEST_ROOT_CERT_ALIAS,
+ TEST_DEFAULT_ROOT_CERT_ALIAS,
RecoveryCertPath.createRecoveryCertPath(TestData.CERT_PATH_1),
vaultParams,
TEST_VAULT_CHALLENGE,
@@ -637,7 +644,7 @@
try {
mRecoverableKeyStoreManager.startRecoverySessionWithCertPath(
TEST_SESSION_ID,
- TEST_ROOT_CERT_ALIAS,
+ TEST_DEFAULT_ROOT_CERT_ALIAS,
RecoveryCertPath.createRecoveryCertPath(emptyCertPath),
TEST_VAULT_PARAMS,
TEST_VAULT_CHALLENGE,
@@ -657,7 +664,7 @@
try {
mRecoverableKeyStoreManager.startRecoverySessionWithCertPath(
TEST_SESSION_ID,
- TEST_ROOT_CERT_ALIAS,
+ TEST_DEFAULT_ROOT_CERT_ALIAS,
RecoveryCertPath.createRecoveryCertPath(shortCertPath),
TEST_VAULT_PARAMS,
TEST_VAULT_CHALLENGE,
@@ -946,12 +953,12 @@
public void setRecoverySecretTypes_updatesShouldCreateSnapshot() throws Exception {
int uid = Binder.getCallingUid();
int userId = UserHandle.getCallingUserId();
- int[] types = new int[]{1, 2, 3};
+ mRecoverableKeyStoreManager.setRecoverySecretTypes(new int[] { 1 });
mRecoverableKeyStoreManager.generateAndStoreKey(TEST_ALIAS);
// Pretend that key was synced
mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);
- mRecoverableKeyStoreManager.setRecoverySecretTypes(types);
+ mRecoverableKeyStoreManager.setRecoverySecretTypes(new int[] { 2 });
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java
index 37482a3..9b09dd1a 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java
@@ -34,6 +34,7 @@
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.KeysEntry;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServiceMetadataEntry;
+import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RootOfTrustEntry;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.UserMetadataEntry;
@SmallTest
@@ -55,6 +56,7 @@
private static final String TEST_SECRET_TYPES = "test-secret-types";
private static final long TEST_COUNTER_ID = -3981205205038476415L;
private static final byte[] TEST_SERVER_PARAMS = "test-server-params".getBytes(UTF_8);
+ private static final String TEST_ROOT_ALIAS = "root_cert_alias";
private static final byte[] TEST_CERT_PATH = "test-cert-path".getBytes(UTF_8);
private static final long TEST_CERT_SERIAL = 1000L;
@@ -135,6 +137,32 @@
checkAllColumns();
}
+ @Test
+ public void onUpgrade_v2_to_v3_to_v4() throws Exception {
+ createV2Tables();
+
+ assertThat(isRootOfTrustTableAvailable()).isFalse(); // V2 doesn't have the table;
+
+ mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 2, /*newVersion=*/ 3);
+
+ assertThat(isRootOfTrustTableAvailable()).isFalse(); // V3 doesn't have the table;
+
+ mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 3,
+ RecoverableKeyStoreDbHelper.DATABASE_VERSION);
+ checkAllColumns();
+ }
+
+ private boolean isRootOfTrustTableAvailable() {
+ ContentValues values = new ContentValues();
+ values.put(RootOfTrustEntry.COLUMN_NAME_USER_ID, TEST_USER_ID);
+ values.put(RootOfTrustEntry.COLUMN_NAME_UID, TEST_UID);
+ values.put(RootOfTrustEntry.COLUMN_NAME_ROOT_ALIAS, TEST_ROOT_ALIAS);
+ values.put(RootOfTrustEntry.COLUMN_NAME_CERT_PATH, TEST_CERT_PATH);
+ values.put(RootOfTrustEntry.COLUMN_NAME_CERT_SERIAL, TEST_CERT_SERIAL);
+ return mDatabase.insert(RootOfTrustEntry.TABLE_NAME, /*nullColumnHack=*/ null, values)
+ > -1;
+ }
+
private void checkAllColumns() throws Exception {
// Check the table containing encrypted application keys
ContentValues values = new ContentValues();
@@ -165,6 +193,7 @@
TEST_SNAPSHOT_VERSION);
values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_SHOULD_CREATE_SNAPSHOT,
TEST_SHOULD_CREATE_SNAPSHOT);
+ values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_ACTIVE_ROOT_OF_TRUST, TEST_ROOT_ALIAS);
values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY, TEST_PUBLIC_KEY);
values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_SECRET_TYPES, TEST_SECRET_TYPES);
values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_COUNTER_ID, TEST_COUNTER_ID);
@@ -175,5 +204,8 @@
mDatabase.insert(RecoveryServiceMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null,
values))
.isGreaterThan(-1L);
+
+ // Check the table about recovery service and root of trust data introduced in V4
+ assertThat(isRootOfTrustTableAvailable()).isTrue();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
index 8b01d97..940745e 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
@@ -49,6 +49,9 @@
public class RecoverableKeyStoreDbTest {
private static final String DATABASE_FILE_NAME = "recoverablekeystore.db";
+ private static final String TEST_ROOT_CERT_ALIAS = "trusted_root";
+ private static final String TEST_ROOT_CERT_ALIAS2 = "another_trusted_root";
+
private RecoverableKeyStoreDb mRecoverableKeyStoreDb;
private File mDatabaseFile;
@@ -284,7 +287,8 @@
Map<String, Integer> statuses = mRecoverableKeyStoreDb.getStatusForAllKeys(uid);
assertThat(statuses).hasSize(3);
- assertThat(statuses).containsEntry(alias, RecoveryController.RECOVERY_STATUS_SYNC_IN_PROGRESS);
+ assertThat(statuses).containsEntry(alias,
+ RecoveryController.RECOVERY_STATUS_SYNC_IN_PROGRESS);
assertThat(statuses).containsEntry(alias2, status);
assertThat(statuses).containsEntry(alias3, status);
@@ -401,26 +405,53 @@
public void setRecoveryServiceCertPath_replaceOldValue() throws Exception {
int userId = 12;
int uid = 10009;
- mRecoverableKeyStoreDb.setRecoveryServiceCertPath(userId, uid, TestData.CERT_PATH_1);
- mRecoverableKeyStoreDb.setRecoveryServiceCertPath(userId, uid, TestData.CERT_PATH_2);
- assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isEqualTo(
+ mRecoverableKeyStoreDb.setRecoveryServiceCertPath(userId, uid, TEST_ROOT_CERT_ALIAS,
+ TestData.CERT_PATH_1);
+ mRecoverableKeyStoreDb.setRecoveryServiceCertPath(userId, uid, TEST_ROOT_CERT_ALIAS,
TestData.CERT_PATH_2);
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid,
+ TEST_ROOT_CERT_ALIAS)).isEqualTo(TestData.CERT_PATH_2);
+ }
+
+ @Test
+ public void setRecoveryServiceCertPath_updateValuesForCorrectRootCert() throws Exception {
+ int userId = 12;
+ int uid = 10009;
+ mRecoverableKeyStoreDb.setRecoveryServiceCertPath(userId, uid, TEST_ROOT_CERT_ALIAS,
+ TestData.CERT_PATH_1);
+ mRecoverableKeyStoreDb.setRecoveryServiceCertPath(userId, uid, TEST_ROOT_CERT_ALIAS2,
+ TestData.CERT_PATH_1);
+
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid,
+ TEST_ROOT_CERT_ALIAS)).isEqualTo(TestData.CERT_PATH_1);
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid,
+ TEST_ROOT_CERT_ALIAS2)).isEqualTo(TestData.CERT_PATH_1);
+
+ mRecoverableKeyStoreDb.setRecoveryServiceCertPath(userId, uid, TEST_ROOT_CERT_ALIAS2,
+ TestData.CERT_PATH_2);
+
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid,
+ TEST_ROOT_CERT_ALIAS)).isEqualTo(TestData.CERT_PATH_1);
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid,
+ TEST_ROOT_CERT_ALIAS2)).isEqualTo(TestData.CERT_PATH_2);
}
@Test
public void getRecoveryServiceCertPath_returnsNullIfNoValue() throws Exception {
int userId = 12;
int uid = 10009;
- assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isNull();
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid,
+ TEST_ROOT_CERT_ALIAS)).isNull();
}
@Test
public void getRecoveryServiceCertPath_returnsInsertedValue() throws Exception {
int userId = 12;
int uid = 10009;
- mRecoverableKeyStoreDb.setRecoveryServiceCertPath(userId, uid, TestData.CERT_PATH_1);
- assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isEqualTo(
+ mRecoverableKeyStoreDb.setRecoveryServiceCertPath(userId, uid, TEST_ROOT_CERT_ALIAS,
TestData.CERT_PATH_1);
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid,
+ TEST_ROOT_CERT_ALIAS)).isEqualTo(TestData.CERT_PATH_1);
}
@Test
@@ -428,25 +459,50 @@
int userId = 12;
int uid = 10009;
- mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid, 1L);
- mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid, 3L);
- assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)).isEqualTo(3L);
+ mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid, TEST_ROOT_CERT_ALIAS, 1L);
+ mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid, TEST_ROOT_CERT_ALIAS, 3L);
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid,
+ TEST_ROOT_CERT_ALIAS)).isEqualTo(3L);
+ }
+
+ @Test
+ public void setRecoveryServiceCertSerial_updateValuesForCorrectRootCert() throws Exception {
+ int userId = 12;
+ int uid = 10009;
+ mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid, TEST_ROOT_CERT_ALIAS, 1L);
+ mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid, TEST_ROOT_CERT_ALIAS2, 1L);
+
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid,
+ TEST_ROOT_CERT_ALIAS)).isEqualTo(1L);
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid,
+ TEST_ROOT_CERT_ALIAS2)).isEqualTo(1L);
+
+ mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid, TEST_ROOT_CERT_ALIAS2, 3L);
+
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid,
+ TEST_ROOT_CERT_ALIAS)).isEqualTo(1L);
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid,
+ TEST_ROOT_CERT_ALIAS2)).isEqualTo(3L);
}
@Test
public void getRecoveryServiceCertSerial_returnsNullIfNoValue() throws Exception {
int userId = 12;
int uid = 10009;
- assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)).isNull();
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid,
+ TEST_ROOT_CERT_ALIAS)).isNull();
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid,
+ TEST_ROOT_CERT_ALIAS2)).isNull();
}
@Test
public void getRecoveryServiceCertSerial_returnsInsertedValue() throws Exception {
int userId = 12;
int uid = 10009;
- mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid, 1234L);
- assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)).isEqualTo(
- 1234L);
+ mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid,
+ TEST_ROOT_CERT_ALIAS, 1234L);
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid,
+ TEST_ROOT_CERT_ALIAS)).isEqualTo(1234L);
}
@Test
@@ -480,6 +536,24 @@
}
@Test
+ public void setActiveRootOfTrust_emptyDefaultValue() throws Exception {
+ int userId = 12;
+ int uid = 10009;
+ assertThat(mRecoverableKeyStoreDb.getActiveRootOfTrust(userId, uid)).isEqualTo(null);
+ }
+
+ @Test
+ public void setActiveRootOfTrust_updateValue() throws Exception {
+ int userId = 12;
+ int uid = 10009;
+ mRecoverableKeyStoreDb.setActiveRootOfTrust(userId, uid, "root");
+ assertThat(mRecoverableKeyStoreDb.getActiveRootOfTrust(userId, uid)).isEqualTo("root");
+
+ mRecoverableKeyStoreDb.setActiveRootOfTrust(userId, uid, "root2");
+ assertThat(mRecoverableKeyStoreDb.getActiveRootOfTrust(userId, uid)).isEqualTo("root2");
+ }
+
+ @Test
public void setRecoverySecretTypes_emptyDefaultValue() throws Exception {
int userId = 12;
int uid = 10009;
@@ -495,11 +569,9 @@
int[] types2 = new int[]{2};
mRecoverableKeyStoreDb.setRecoverySecretTypes(userId, uid, types1);
- assertThat(mRecoverableKeyStoreDb.getRecoverySecretTypes(userId, uid)).isEqualTo(
- types1);
+ assertThat(mRecoverableKeyStoreDb.getRecoverySecretTypes(userId, uid)).isEqualTo(types1);
mRecoverableKeyStoreDb.setRecoverySecretTypes(userId, uid, types2);
- assertThat(mRecoverableKeyStoreDb.getRecoverySecretTypes(userId, uid)).isEqualTo(
- types2);
+ assertThat(mRecoverableKeyStoreDb.getRecoverySecretTypes(userId, uid)).isEqualTo(types2);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
index d702318..ee0ad39 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
@@ -16,55 +16,129 @@
package com.android.server.pm;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import android.app.AppGlobals;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.os.BaseBundle;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.PersistableBundle;
+import android.os.RemoteException;
import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
+import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;
import com.android.servicestests.apps.suspendtestapp.SuspendTestReceiver;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@RunWith(AndroidJUnit4.class)
-@MediumTest
+@LargeTest
public class SuspendPackagesTest {
private static final String TEST_APP_PACKAGE_NAME = SuspendTestReceiver.PACKAGE_NAME;
private static final String[] PACKAGES_TO_SUSPEND = new String[]{TEST_APP_PACKAGE_NAME};
+ public static final String INSTRUMENTATION_PACKAGE = "com.android.frameworks.servicestests";
+ public static final String ACTION_REPORT_MY_PACKAGE_SUSPENDED =
+ INSTRUMENTATION_PACKAGE + ".action.REPORT_MY_PACKAGE_SUSPENDED";
+ public static final String ACTION_REPORT_MY_PACKAGE_UNSUSPENDED =
+ INSTRUMENTATION_PACKAGE + ".action.REPORT_MY_PACKAGE_UNSUSPENDED";
+
private Context mContext;
private PackageManager mPackageManager;
private Handler mReceiverHandler;
private ComponentName mTestReceiverComponent;
+ private AppCommunicationReceiver mAppCommsReceiver;
+
+ private static final class AppCommunicationReceiver extends BroadcastReceiver {
+ private Context context;
+ private boolean registered;
+ private SynchronousQueue<Intent> intentQueue = new SynchronousQueue<>();
+
+ AppCommunicationReceiver(Context context) {
+ this.context = context;
+ }
+
+ void register(Handler handler) {
+ registered = true;
+ final IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(ACTION_REPORT_MY_PACKAGE_SUSPENDED);
+ intentFilter.addAction(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED);
+ context.registerReceiver(this, intentFilter, null, handler);
+ }
+
+ void unregister() {
+ if (registered) {
+ context.unregisterReceiver(this);
+ }
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ try {
+ intentQueue.offer(intent, 5, TimeUnit.SECONDS);
+ } catch (InterruptedException ie) {
+ throw new RuntimeException("Receiver thread interrupted", ie);
+ }
+ }
+
+ Intent receiveIntentFromApp() {
+ if (!registered) {
+ throw new IllegalStateException("Receiver not registered");
+ }
+ final Intent intent;
+ try {
+ intent = intentQueue.poll(5, TimeUnit.SECONDS);
+ } catch (InterruptedException ie) {
+ throw new RuntimeException("Interrupted while waiting for app broadcast", ie);
+ }
+ assertNotNull("No intent received from app within 5 seconds", intent);
+ return intent;
+ }
+ }
@Before
public void setUp() {
mContext = InstrumentationRegistry.getTargetContext();
mPackageManager = mContext.getPackageManager();
- mPackageManager.setPackagesSuspended(PACKAGES_TO_SUSPEND, false, null, null, null);
mReceiverHandler = new Handler(Looper.getMainLooper());
mTestReceiverComponent = new ComponentName(TEST_APP_PACKAGE_NAME,
SuspendTestReceiver.class.getCanonicalName());
+ IPackageManager ipm = AppGlobals.getPackageManager();
+ try {
+ // Otherwise implicit broadcasts will not be delivered.
+ ipm.setPackageStoppedState(TEST_APP_PACKAGE_NAME, false, mContext.getUserId());
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ unsuspendTestPackage();
+ mAppCommsReceiver = new AppCommunicationReceiver(mContext);
}
+ /**
+ * Care should be taken when used with {@link #mAppCommsReceiver} in the same test as both use
+ * the same handler.
+ */
private Bundle requestAppAction(String action) throws InterruptedException {
final AtomicReference<Bundle> result = new AtomicReference<>();
final CountDownLatch receiverLatch = new CountDownLatch(1);
@@ -98,6 +172,24 @@
assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
}
+ private void unsuspendTestPackage() {
+ final String[] unchangedPackages = mPackageManager.setPackagesSuspended(
+ PACKAGES_TO_SUSPEND, false, null, null, null);
+ assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
+ }
+
+
+ private static void assertSameExtras(String message, BaseBundle expected, BaseBundle received) {
+ if (expected != null) {
+ expected.get(""); // hack to unparcel the bundles.
+ }
+ if (received != null) {
+ received.get("");
+ }
+ assertTrue(message + ": [expected: " + expected + "; received: " + received + "]",
+ BaseBundle.kindofEquals(expected, received));
+ }
+
@Test
public void testIsPackageSuspended() {
suspendTestPackage(null, null);
@@ -109,19 +201,73 @@
public void testSuspendedStateFromApp() throws Exception {
Bundle resultFromApp = requestAppAction(SuspendTestReceiver.ACTION_GET_SUSPENDED_STATE);
assertFalse(resultFromApp.getBoolean(SuspendTestReceiver.EXTRA_SUSPENDED, true));
- assertNull(resultFromApp.getParcelable(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
+ assertNull(resultFromApp.getBundle(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
- final PersistableBundle appExtras = getExtras("appExtras", 20, "20", 0.2);
+ final PersistableBundle appExtras = getExtras("testSuspendedStateFromApp", 20, "20", 0.2);
suspendTestPackage(appExtras, null);
resultFromApp = requestAppAction(SuspendTestReceiver.ACTION_GET_SUSPENDED_STATE);
assertTrue("resultFromApp:suspended is false",
resultFromApp.getBoolean(SuspendTestReceiver.EXTRA_SUSPENDED));
- final PersistableBundle receivedAppExtras =
- resultFromApp.getParcelable(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS);
- receivedAppExtras.get(""); // hack to unparcel the bundles
- appExtras.get("");
- assertTrue("Received app extras " + receivedAppExtras + " different to the ones supplied",
- BaseBundle.kindofEquals(appExtras, receivedAppExtras));
+ final Bundle receivedAppExtras =
+ resultFromApp.getBundle(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS);
+ assertSameExtras("Received app extras different to the ones supplied",
+ appExtras, receivedAppExtras);
+ }
+
+ @Test
+ public void testMyPackageSuspendedUnsuspended() {
+ mAppCommsReceiver.register(mReceiverHandler);
+ final PersistableBundle appExtras = getExtras("testMyPackageSuspendBroadcasts", 1, "1", .1);
+ suspendTestPackage(appExtras, null);
+ Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertTrue("MY_PACKAGE_SUSPENDED delivery not reported",
+ ACTION_REPORT_MY_PACKAGE_SUSPENDED.equals(intentFromApp.getAction()));
+ assertSameExtras("Received app extras different to the ones supplied", appExtras,
+ intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
+ unsuspendTestPackage();
+ intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertTrue("MY_PACKAGE_UNSUSPENDED delivery not reported",
+ ACTION_REPORT_MY_PACKAGE_UNSUSPENDED.equals(intentFromApp.getAction()));
+ }
+
+ @Test
+ public void testUpdatingAppExtras() {
+ mAppCommsReceiver.register(mReceiverHandler);
+ final PersistableBundle extras1 = getExtras("testMyPackageSuspendedOnChangingExtras", 1,
+ "1", 0.1);
+ suspendTestPackage(extras1, null);
+ Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertTrue("MY_PACKAGE_SUSPENDED delivery not reported",
+ ACTION_REPORT_MY_PACKAGE_SUSPENDED.equals(intentFromApp.getAction()));
+ assertSameExtras("Received app extras different to the ones supplied", extras1,
+ intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
+ final PersistableBundle extras2 = getExtras("testMyPackageSuspendedOnChangingExtras", 2,
+ "2", 0.2);
+ mPackageManager.setSuspendedPackageAppExtras(TEST_APP_PACKAGE_NAME, extras2);
+ intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertTrue("MY_PACKAGE_SUSPENDED delivery not reported",
+ ACTION_REPORT_MY_PACKAGE_SUSPENDED.equals(intentFromApp.getAction()));
+ assertSameExtras("Received app extras different to the updated extras", extras2,
+ intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
+ }
+
+ @Test
+ public void testCannotSuspendSelf() {
+ final String[] unchangedPkgs = mPackageManager.setPackagesSuspended(
+ new String[]{mContext.getOpPackageName()}, true, null, null, null);
+ assertTrue(unchangedPkgs.length == 1);
+ assertEquals(mContext.getOpPackageName(), unchangedPkgs[0]);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mAppCommsReceiver.unregister();
+ Thread.sleep(250); // To prevent any race with the next registerReceiver
+ }
+
+ @FunctionalInterface
+ interface Condition {
+ boolean isTrue();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
index 57dd808..6769e40 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
@@ -18,8 +18,12 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -99,16 +103,23 @@
private MockSurfaceBuildingContainer mHost;
private Dimmer mDimmer;
private SurfaceControl.Transaction mTransaction;
+ private Dimmer.SurfaceAnimatorStarter mSurfaceAnimatorStarter;
+
+ private static class SurfaceAnimatorStarterImpl implements Dimmer.SurfaceAnimatorStarter {
+ @Override
+ public void startAnimation(SurfaceAnimator surfaceAnimator, SurfaceControl.Transaction t,
+ AnimationAdapter anim, boolean hidden) {
+ surfaceAnimator.mAnimationFinishedCallback.run();
+ }
+ }
@Before
public void setUp() throws Exception {
super.setUp();
mHost = new MockSurfaceBuildingContainer();
-
+ mSurfaceAnimatorStarter = spy(new SurfaceAnimatorStarterImpl());
mTransaction = mock(SurfaceControl.Transaction.class);
- mDimmer = new Dimmer(mHost,
- (surfaceAnimator, t, anim, hidden) -> surfaceAnimator.mAnimationFinishedCallback
- .run());
+ mDimmer = new Dimmer(mHost, mSurfaceAnimatorStarter);
}
@Test
@@ -202,6 +213,8 @@
mDimmer.resetDimStates();
mDimmer.updateDims(mTransaction, new Rect());
+ verify(mSurfaceAnimatorStarter).startAnimation(any(SurfaceAnimator.class), any(
+ SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean());
verify(dimLayer).destroy();
}
@@ -243,6 +256,25 @@
verify(mTransaction).setPosition(dimLayer, 10, 10);
}
+ @Test
+ public void testRemoveDimImmediately() throws Exception {
+ TestWindowContainer child = new TestWindowContainer();
+ mHost.addChild(child, 0);
+
+ mDimmer.dimAbove(mTransaction, child, 1);
+ SurfaceControl dimLayer = getDimLayer();
+ mDimmer.updateDims(mTransaction, new Rect());
+ verify(mTransaction, times(1)).show(dimLayer);
+
+ reset(mSurfaceAnimatorStarter);
+ mDimmer.dontAnimateExit();
+ mDimmer.resetDimStates();
+ mDimmer.updateDims(mTransaction, new Rect());
+ verify(mSurfaceAnimatorStarter, never()).startAnimation(any(SurfaceAnimator.class), any(
+ SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean());
+ verify(mTransaction).destroy(dimLayer);
+ }
+
private SurfaceControl getDimLayer() {
return mDimmer.mDimState.mDimLayer;
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index 64501e4..553d658 100644
--- a/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -197,4 +197,16 @@
assertEquals(1, appsCaptor.getValue().length);
assertEquals(mMockLeash, appsCaptor.getValue()[0].leash);
}
+
+ @Test
+ public void testRemovedBeforeStarted() throws Exception {
+ final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
+ final AnimationAdapter adapter = mController.createAnimationAdapter(win.mAppToken,
+ new Point(50, 100), new Rect(50, 100, 150, 150));
+ adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
+ win.mAppToken.removeImmediately();
+ mController.goodToGo();
+ verifyZeroInteractions(mMockRunner);
+ verify(mFinishedCallback).onAnimationFinished(eq(adapter));
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowSurfacePlacerTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowSurfacePlacerTest.java
new file mode 100644
index 0000000..e173b7d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowSurfacePlacerTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
+import static android.view.WindowManager.TRANSIT_TASK_OPEN;
+import static junit.framework.Assert.assertEquals;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.WindowManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class WindowSurfacePlacerTest extends WindowTestsBase {
+
+ private WindowSurfacePlacer mWindowSurfacePlacer;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ mWindowSurfacePlacer = new WindowSurfacePlacer(sWm);
+ }
+
+ @Test
+ public void testTranslucentOpen() throws Exception {
+ synchronized (sWm.mWindowMap) {
+ final AppWindowToken behind = createAppWindowToken(mDisplayContent,
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final AppWindowToken translucentOpening = createAppWindowToken(mDisplayContent,
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ translucentOpening.setFillsParent(false);
+ translucentOpening.setHidden(true);
+ sWm.mOpeningApps.add(behind);
+ sWm.mOpeningApps.add(translucentOpening);
+ assertEquals(WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN,
+ mWindowSurfacePlacer.maybeUpdateTransitToTranslucentAnim(TRANSIT_TASK_OPEN));
+ }
+ }
+
+ @Test
+ public void testTranslucentClose() throws Exception {
+ synchronized (sWm.mWindowMap) {
+ final AppWindowToken behind = createAppWindowToken(mDisplayContent,
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final AppWindowToken translucentClosing = createAppWindowToken(mDisplayContent,
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ translucentClosing.setFillsParent(false);
+ sWm.mClosingApps.add(translucentClosing);
+ assertEquals(WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE,
+ mWindowSurfacePlacer.maybeUpdateTransitToTranslucentAnim(TRANSIT_TASK_CLOSE));
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 6fa2740..d2eee68 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -173,6 +173,8 @@
mDisplayContent.removeImmediately();
sWm.mInputMethodTarget = null;
+ sWm.mClosingApps.clear();
+ sWm.mOpeningApps.clear();
}
// Wait until everything is really cleaned up.
diff --git a/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk b/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk
index 40a34b9..afdde72 100644
--- a/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk
+++ b/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk
@@ -17,14 +17,18 @@
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
LOCAL_COMPATIBILITY_SUITE := device-tests
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_SRC_FILES += ../../src/com/android/server/pm/SuspendPackagesTest.java
LOCAL_PACKAGE_NAME := SuspendTestApp
LOCAL_DEX_PREOPT := false
LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/services/tests/servicestests/test-apps/SuspendTestApp/AndroidManifest.xml b/services/tests/servicestests/test-apps/SuspendTestApp/AndroidManifest.xml
index 70a1fd0..ce6a27a 100644
--- a/services/tests/servicestests/test-apps/SuspendTestApp/AndroidManifest.xml
+++ b/services/tests/servicestests/test-apps/SuspendTestApp/AndroidManifest.xml
@@ -21,7 +21,12 @@
<activity android:name=".SuspendTestActivity"
android:exported="true" />
<receiver android:name=".SuspendTestReceiver"
- android:exported="true" />
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MY_PACKAGE_SUSPENDED" />
+ <action android:name="android.intent.action.MY_PACKAGE_UNSUSPENDED" />
+ </intent-filter>
+ </receiver>
</application>
</manifest>
\ No newline at end of file
diff --git a/services/tests/servicestests/test-apps/SuspendTestApp/src/com/android/servicestests/apps/suspendtestapp/SuspendTestReceiver.java b/services/tests/servicestests/test-apps/SuspendTestApp/src/com/android/servicestests/apps/suspendtestapp/SuspendTestReceiver.java
index 6f353a0..90a9f01 100644
--- a/services/tests/servicestests/test-apps/SuspendTestApp/src/com/android/servicestests/apps/suspendtestapp/SuspendTestReceiver.java
+++ b/services/tests/servicestests/test-apps/SuspendTestApp/src/com/android/servicestests/apps/suspendtestapp/SuspendTestReceiver.java
@@ -16,12 +16,15 @@
package com.android.servicestests.apps.suspendtestapp;
+import static com.android.server.pm.SuspendPackagesTest.ACTION_REPORT_MY_PACKAGE_SUSPENDED;
+import static com.android.server.pm.SuspendPackagesTest.ACTION_REPORT_MY_PACKAGE_UNSUSPENDED;
+import static com.android.server.pm.SuspendPackagesTest.INSTRUMENTATION_PACKAGE;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
-import android.os.PersistableBundle;
import android.util.Log;
public class SuspendTestReceiver extends BroadcastReceiver {
@@ -34,21 +37,33 @@
public static final String EXTRA_SUSPENDED_APP_EXTRAS =
PACKAGE_NAME + ".extra.SUSPENDED_APP_EXTRAS";
- private PackageManager mPm;
-
@Override
public void onReceive(Context context, Intent intent) {
- mPm = context.getPackageManager();
- Log.d(TAG, "Received request action " + intent.getAction());
+ final PackageManager packageManager = context.getPackageManager();
+ Log.d(TAG, "Received action " + intent.getAction());
+ final Bundle appExtras;
switch (intent.getAction()) {
case ACTION_GET_SUSPENDED_STATE:
final Bundle result = new Bundle();
- final boolean suspended = mPm.isPackageSuspended();
- final PersistableBundle appExtras = mPm.getSuspendedPackageAppExtras();
+ final boolean suspended = packageManager.isPackageSuspended();
+ appExtras = packageManager.getSuspendedPackageAppExtras();
result.putBoolean(EXTRA_SUSPENDED, suspended);
- result.putParcelable(EXTRA_SUSPENDED_APP_EXTRAS, appExtras);
+ result.putBundle(EXTRA_SUSPENDED_APP_EXTRAS, appExtras);
setResult(0, null, result);
break;
+ case Intent.ACTION_MY_PACKAGE_SUSPENDED:
+ appExtras = intent.getBundleExtra(Intent.EXTRA_SUSPENDED_PACKAGE_EXTRAS);
+ final Intent reportSuspendIntent = new Intent(ACTION_REPORT_MY_PACKAGE_SUSPENDED)
+ .putExtra(EXTRA_SUSPENDED_APP_EXTRAS, appExtras)
+ .setPackage(INSTRUMENTATION_PACKAGE);
+ context.sendBroadcast(reportSuspendIntent);
+ break;
+ case Intent.ACTION_MY_PACKAGE_UNSUSPENDED:
+ final Intent reportUnsuspendIntent =
+ new Intent(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED)
+ .setPackage(INSTRUMENTATION_PACKAGE);
+ context.sendBroadcast(reportUnsuspendIntent);
+ break;
default:
Log.e(TAG, "Unknown action: " + intent.getAction());
}
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index 00826e0..b070e03 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -16,6 +16,7 @@
package com.android.server.usage;
import android.app.usage.ConfigurationStats;
+import android.app.usage.EventStats;
import android.app.usage.TimeSparseArray;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStats;
@@ -23,10 +24,18 @@
import android.util.ArrayMap;
import android.util.ArraySet;
+import java.util.List;
+
class IntervalStats {
public long beginTime;
public long endTime;
public long lastTimeSaved;
+ public long lastInteractiveTime;
+ public long lastNonInteractiveTime;
+ public long interactiveDuration;
+ public int interactiveCount;
+ public long nonInteractiveDuration;
+ public int nonInteractiveCount;
public final ArrayMap<String, UsageStats> packageStats = new ArrayMap<>();
public final ArrayMap<Configuration, ConfigurationStats> configurations = new ArrayMap<>();
public Configuration activeConfiguration;
@@ -171,6 +180,60 @@
usageStats.mAppLaunchCount += 1;
}
+ private void commitInteractiveTime(long timeStamp) {
+ if (lastInteractiveTime != 0) {
+ interactiveDuration += timeStamp - lastInteractiveTime;
+ lastInteractiveTime = 0;
+ }
+ if (lastNonInteractiveTime != 0) {
+ nonInteractiveDuration += timeStamp - lastNonInteractiveTime;
+ lastNonInteractiveTime = 0;
+ }
+ }
+
+ void commitTime(long timeStamp) {
+ commitInteractiveTime(timeStamp);
+ }
+
+ void updateScreenInteractive(long timeStamp) {
+ if (lastInteractiveTime != 0) {
+ // Already interactive, just keep running.
+ return;
+ }
+ commitInteractiveTime(timeStamp);
+ lastInteractiveTime = timeStamp;
+ interactiveCount++;
+ }
+
+ void updateScreenNonInteractive(long timeStamp) {
+ if (lastNonInteractiveTime != 0) {
+ // Already non-interactive, just keep running.
+ return;
+ }
+ commitInteractiveTime(timeStamp);
+ lastNonInteractiveTime = timeStamp;
+ nonInteractiveCount++;
+ }
+
+ private void addOneEventStats(List<EventStats> out, int event, int count, long duration) {
+ if (count != 0 || duration != 0) {
+ EventStats ev = new EventStats();
+ ev.mEventType = event;
+ ev.mCount = count;
+ ev.mTotalTime = duration;
+ ev.mBeginTimeStamp = beginTime;
+ ev.mEndTimeStamp = endTime;
+ out.add(ev);
+ }
+ }
+
+ void addEventStatsTo(List<EventStats> out) {
+ addOneEventStats(out, UsageEvents.Event.SCREEN_INTERACTIVE, interactiveCount,
+ interactiveDuration);
+ addOneEventStats(out, UsageEvents.Event.SCREEN_NON_INTERACTIVE, nonInteractiveCount,
+ nonInteractiveDuration);
+ }
+
private String getCachedStringRef(String str) {
final int index = mStringCache.indexOf(str);
if (index < 0) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index b8317b4..2258b24 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -25,6 +25,7 @@
import android.app.admin.DevicePolicyManagerInternal;
import android.app.usage.AppStandbyInfo;
import android.app.usage.ConfigurationStats;
+import android.app.usage.EventStats;
import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManager;
@@ -486,6 +487,23 @@
/**
* Called by the Binder stub.
*/
+ List<EventStats> queryEventStats(int userId, int bucketType, long beginTime,
+ long endTime) {
+ synchronized (mLock) {
+ final long timeNow = checkAndGetTimeLocked();
+ if (!validRange(timeNow, beginTime, endTime)) {
+ return null;
+ }
+
+ final UserUsageStatsService service =
+ getUserDataAndInitializeIfNeededLocked(userId, timeNow);
+ return service.queryEventStats(bucketType, beginTime, endTime);
+ }
+ }
+
+ /**
+ * Called by the Binder stub.
+ */
UsageEvents queryEvents(int userId, long beginTime, long endTime,
boolean shouldObfuscateInstantApps) {
synchronized (mLock) {
@@ -713,6 +731,28 @@
}
@Override
+ public ParceledListSlice<EventStats> queryEventStats(int bucketType,
+ long beginTime, long endTime, String callingPackage) throws RemoteException {
+ if (!hasPermission(callingPackage)) {
+ return null;
+ }
+
+ final int userId = UserHandle.getCallingUserId();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ final List<EventStats> results =
+ UsageStatsService.this.queryEventStats(userId, bucketType,
+ beginTime, endTime);
+ if (results != null) {
+ return new ParceledListSlice<>(results);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return null;
+ }
+
+ @Override
public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) {
if (!hasPermission(callingPackage)) {
return null;
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index bcfc421..2287b27 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -27,6 +27,7 @@
import android.app.usage.UsageStats;
import android.content.res.Configuration;
import android.util.ArrayMap;
+import android.util.Pair;
import java.io.IOException;
import java.net.ProtocolException;
@@ -37,6 +38,9 @@
final class UsageStatsXmlV1 {
private static final String TAG = "UsageStatsXmlV1";
+ private static final String INTERACTIVE_TAG = "interactive";
+ private static final String NON_INTERACTIVE_TAG = "non-interactive";
+
private static final String PACKAGES_TAG = "packages";
private static final String PACKAGE_TAG = "package";
@@ -99,6 +103,14 @@
}
}
+ private static Pair<Integer, Long> loadCountAndTime(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ int count = XmlUtils.readIntAttribute(parser, COUNT_ATTR, 0);
+ long time = XmlUtils.readLongAttribute(parser, TIME_ATTR, 0);
+ XmlUtils.skipCurrentTag(parser);
+ return new Pair<>(count, time);
+ }
+
private static void loadChooserCounts(
XmlPullParser parser, UsageStats usageStats, String action)
throws XmlPullParserException, IOException {
@@ -202,6 +214,14 @@
xml.endTag(null, PACKAGE_TAG);
}
+ private static void writeCountAndTime(XmlSerializer xml, String tag, int count, long time)
+ throws IOException {
+ xml.startTag(null, tag);
+ XmlUtils.writeIntAttribute(xml, COUNT_ATTR, count);
+ XmlUtils.writeLongAttribute(xml, TIME_ATTR, time);
+ xml.endTag(null, tag);
+ }
+
private static void writeChooserCounts(XmlSerializer xml, final UsageStats usageStats)
throws IOException {
if (usageStats == null || usageStats.mChooserCounts == null ||
@@ -320,6 +340,18 @@
final String tag = parser.getName();
switch (tag) {
+ case INTERACTIVE_TAG: {
+ Pair<Integer, Long> result = loadCountAndTime(parser);
+ statsOut.interactiveCount = result.first;
+ statsOut.interactiveDuration = result.second;
+ } break;
+
+ case NON_INTERACTIVE_TAG: {
+ Pair<Integer, Long> result = loadCountAndTime(parser);
+ statsOut.nonInteractiveCount = result.first;
+ statsOut.nonInteractiveDuration = result.second;
+ } break;
+
case PACKAGE_TAG:
loadUsageStats(parser, statsOut);
break;
@@ -346,6 +378,11 @@
public static void write(XmlSerializer xml, IntervalStats stats) throws IOException {
XmlUtils.writeLongAttribute(xml, END_TIME_ATTR, stats.endTime - stats.beginTime);
+ writeCountAndTime(xml, INTERACTIVE_TAG, stats.interactiveCount, stats.interactiveDuration);
+
+ writeCountAndTime(xml, NON_INTERACTIVE_TAG, stats.nonInteractiveCount,
+ stats.nonInteractiveDuration);
+
xml.startTag(null, PACKAGES_TAG);
final int statsCount = stats.packageStats.size();
for (int i = 0; i < statsCount; i++) {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index afc3d59..6ad374b 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -17,6 +17,7 @@
package com.android.server.usage;
import android.app.usage.ConfigurationStats;
+import android.app.usage.EventStats;
import android.app.usage.TimeSparseArray;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStats;
@@ -191,21 +192,31 @@
}
for (IntervalStats stats : mCurrentStats) {
- if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE) {
- stats.updateConfigurationStats(newFullConfig, event.mTimeStamp);
- } else if (event.mEventType == UsageEvents.Event.CHOOSER_ACTION) {
- stats.updateChooserCounts(event.mPackage, event.mContentType, event.mAction);
- String[] annotations = event.mContentAnnotations;
- if (annotations != null) {
- for (String annotation : annotations) {
- stats.updateChooserCounts(event.mPackage, annotation, event.mAction);
+ switch (event.mEventType) {
+ case UsageEvents.Event.CONFIGURATION_CHANGE: {
+ stats.updateConfigurationStats(newFullConfig, event.mTimeStamp);
+ } break;
+ case UsageEvents.Event.CHOOSER_ACTION: {
+ stats.updateChooserCounts(event.mPackage, event.mContentType, event.mAction);
+ String[] annotations = event.mContentAnnotations;
+ if (annotations != null) {
+ for (String annotation : annotations) {
+ stats.updateChooserCounts(event.mPackage, annotation, event.mAction);
+ }
}
- }
- } else {
- stats.update(event.mPackage, event.mTimeStamp, event.mEventType);
- if (incrementAppLaunch) {
- stats.incrementAppLaunchCount(event.mPackage);
- }
+ } break;
+ case UsageEvents.Event.SCREEN_INTERACTIVE: {
+ stats.updateScreenInteractive(event.mTimeStamp);
+ } break;
+ case UsageEvents.Event.SCREEN_NON_INTERACTIVE: {
+ stats.updateScreenNonInteractive(event.mTimeStamp);
+ } break;
+ default: {
+ stats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+ if (incrementAppLaunch) {
+ stats.incrementAppLaunchCount(event.mPackage);
+ }
+ } break;
}
}
@@ -246,6 +257,15 @@
}
};
+ private static final StatCombiner<EventStats> sEventStatsCombiner =
+ new StatCombiner<EventStats>() {
+ @Override
+ public void combine(IntervalStats stats, boolean mutable,
+ List<EventStats> accResult) {
+ stats.addEventStatsTo(accResult);
+ }
+ };
+
/**
* Generic query method that selects the appropriate IntervalStats for the specified time range
* and bucket, then calls the {@link com.android.server.usage.UsageStatsDatabase.StatCombiner}
@@ -325,6 +345,10 @@
return queryStats(bucketType, beginTime, endTime, sConfigStatsCombiner);
}
+ List<EventStats> queryEventStats(int bucketType, long beginTime, long endTime) {
+ return queryStats(bucketType, beginTime, endTime, sEventStatsCombiner);
+ }
+
UsageEvents queryEvents(final long beginTime, final long endTime,
boolean obfuscateInstantApps) {
final ArraySet<String> names = new ArraySet<>();
@@ -448,6 +472,7 @@
}
stat.updateConfigurationStats(null, mDailyExpiryDate.getTimeInMillis() - 1);
+ stat.commitTime(mDailyExpiryDate.getTimeInMillis() - 1);
}
persistActiveStats();
@@ -640,6 +665,18 @@
}
}
+ void printEventAggregation(IndentingPrintWriter pw, String label, int count, long duration,
+ boolean prettyDates) {
+ if (count != 0 || duration != 0) {
+ pw.print(label);
+ pw.print(": ");
+ pw.print(count);
+ pw.print("x for ");
+ pw.print(formatElapsedTime(duration, prettyDates));
+ pw.println();
+ }
+ }
+
void printIntervalStats(IndentingPrintWriter pw, IntervalStats stats,
boolean prettyDates, boolean skipEvents, String pkg) {
if (prettyDates) {
@@ -713,6 +750,13 @@
pw.println();
}
pw.decreaseIndent();
+ pw.println("event aggregations");
+ pw.increaseIndent();
+ printEventAggregation(pw, "screen-interactive", stats.interactiveCount,
+ stats.interactiveDuration, prettyDates);
+ printEventAggregation(pw, "screen-non-interactive", stats.nonInteractiveCount,
+ stats.nonInteractiveDuration, prettyDates);
+ pw.decreaseIndent();
}
// The last 24 hours of events is already printed in the non checkin dump
@@ -781,6 +825,10 @@
return "SLICE_PINNED";
case UsageEvents.Event.SLICE_PINNED_PRIV:
return "SLICE_PINNED_PRIV";
+ case UsageEvents.Event.SCREEN_INTERACTIVE:
+ return "SCREEN_INTERACTIVE";
+ case UsageEvents.Event.SCREEN_NON_INTERACTIVE:
+ return "SCREEN_NON_INTERACTIVE";
default:
return "UNKNOWN";
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index c79eec0..4683161 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -397,6 +397,15 @@
public static final String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
/**
+ * Where there is no preloaded voicemail number on a SIM card, specifies the carrier's default
+ * voicemail number for roaming network.
+ * When empty string, no default voicemail number is specified for roaming network.
+ * @hide
+ */
+ public static final String KEY_DEFAULT_VM_NUMBER_ROAMING_STRING =
+ "default_vm_number_roaming_string";
+
+ /**
* Flag that specifies to use the user's own phone number as the voicemail number when there is
* no pre-loaded voicemail number on the SIM card.
* <p>
@@ -951,6 +960,8 @@
* If user has explicitly disabled some packages in the list, won't re-enable.
* Other carrier specific apps which are not in this list may be disabled for current carrier,
* and only be re-enabled when this config for another carrier includes it.
+ *
+ * @hide
*/
public static final String KEY_ENABLE_APPS_STRING_ARRAY = "enable_apps_string_array";
@@ -1929,6 +1940,7 @@
sDefaults.putBoolean(KEY_NOTIFY_HANDOVER_VIDEO_FROM_LTE_TO_WIFI_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORT_DOWNGRADE_VT_TO_AUDIO_BOOL, true);
sDefaults.putString(KEY_DEFAULT_VM_NUMBER_STRING, "");
+ sDefaults.putString(KEY_DEFAULT_VM_NUMBER_ROAMING_STRING, "");
sDefaults.putBoolean(KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL, false);
sDefaults.putBoolean(KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, true);
sDefaults.putBoolean(KEY_VILTE_DATA_IS_METERED_BOOL, true);
diff --git a/telephony/java/android/telephony/LocationAccessPolicy.java b/telephony/java/android/telephony/LocationAccessPolicy.java
index 6480aab..6db8e82 100644
--- a/telephony/java/android/telephony/LocationAccessPolicy.java
+++ b/telephony/java/android/telephony/LocationAccessPolicy.java
@@ -40,17 +40,19 @@
*/
public final class LocationAccessPolicy {
private static final String LOG_TAG = LocationAccessPolicy.class.getSimpleName();
+
/**
* API to determine if the caller has permissions to get cell location.
*
* @param pkgName Package name of the application requesting access
* @param uid The uid of the package
* @param pid The pid of the package
+ * @param throwOnDeniedPermission Whether to throw if the location permission is denied.
* @return boolean true or false if permissions is granted
*/
public static boolean canAccessCellLocation(@NonNull Context context, @NonNull String pkgName,
- int uid, int pid) throws SecurityException {
- Trace.beginSection("TelephonyLocationCheck");
+ int uid, int pid, boolean throwOnDeniedPermission) throws SecurityException {
+ Trace.beginSection("TelephonyLohcationCheck");
try {
// Always allow the phone process to access location. This avoid breaking legacy code
// that rely on public-facing APIs to access cell location, and it doesn't create a
@@ -65,9 +67,11 @@
// where a legacy app the user is not using tracks their location.
// Granting ACCESS_FINE_LOCATION to an app automatically grants it
// ACCESS_COARSE_LOCATION.
-
- if (context.checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION, pid, uid) ==
- PackageManager.PERMISSION_DENIED) {
+ if (throwOnDeniedPermission) {
+ context.enforcePermission(Manifest.permission.ACCESS_COARSE_LOCATION,
+ pid, uid, "canAccessCellLocation");
+ } else if (context.checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION,
+ pid, uid) == PackageManager.PERMISSION_DENIED) {
return false;
}
final int opCode = AppOpsManager.permissionToOpCode(
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 77413d9c..936505c 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -335,7 +335,7 @@
return this.mCountryIso;
}
- /** @return whether the subscription is an embedded one. */
+ /** @return whether the subscription is an eUICC one. */
public boolean isEmbedded() {
return this.mIsEmbedded;
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 472a6fb..7664b94 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1925,26 +1925,28 @@
*
* @param info The subscription to check.
* @return whether the app is authorized to manage this subscription per its metadata.
- * @throws UnsupportedOperationException if this subscription is not embedded.
+ * @throws IllegalArgumentException if this subscription is not embedded.
*/
public boolean canManageSubscription(SubscriptionInfo info) {
return canManageSubscription(info, mContext.getPackageName());
}
/**
- * Checks whether the given app is authorized to manage the given subscription according to its
- * metadata. Only supported for embedded subscriptions (if {@code SubscriptionInfo#isEmbedded}
+ * Checks whether the given app is authorized to manage the given subscription. An app can only
+ * be authorized if it is included in the {@link android.telephony.UiccAccessRule} of the
+ * {@link android.telephony.SubscriptionInfo} with the access status.
+ * Only supported for embedded subscriptions (if {@link SubscriptionInfo#isEmbedded}
* returns true).
*
* @param info The subscription to check.
* @param packageName Package name of the app to check.
- * @return whether the app is authorized to manage this subscription per its metadata.
- * @throws UnsupportedOperationException if this subscription is not embedded.
+ * @return whether the app is authorized to manage this subscription per its access rules.
+ * @throws IllegalArgumentException if this subscription is not embedded.
* @hide
*/
public boolean canManageSubscription(SubscriptionInfo info, String packageName) {
if (!info.isEmbedded()) {
- throw new UnsupportedOperationException("Not an embedded subscription");
+ throw new IllegalArgumentException("Not an embedded subscription");
}
if (info.getAccessRules() == null) {
return false;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a12a7a0..da5bd84 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -6349,34 +6349,39 @@
*
* @param enable Whether to enable mobile data.
*
- * @deprecated use {@link #setUserMobileDataEnabled(boolean)} instead.
*/
- @Deprecated
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setDataEnabled(boolean enable) {
- setUserMobileDataEnabled(enable);
+ setDataEnabled(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enable);
}
/**
* @hide
- * @deprecated use {@link #setUserMobileDataEnabled(boolean)} instead.
+ * @deprecated use {@link #setDataEnabled(boolean)} instead.
*/
@SystemApi
@Deprecated
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setDataEnabled(int subId, boolean enable) {
- setUserMobileDataEnabled(subId, enable);
+ try {
+ Log.d(TAG, "setDataEnabled: enabled=" + enable);
+ ITelephony telephony = getITelephony();
+ if (telephony != null)
+ telephony.setUserDataEnabled(subId, enable);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#setUserDataEnabled", e);
+ }
}
/**
- * @deprecated use {@link #isUserMobileDataEnabled()} instead.
+ * @deprecated use {@link #isDataEnabled()} instead.
* @hide
*/
@SystemApi
@Deprecated
public boolean getDataEnabled() {
- return isUserMobileDataEnabled();
+ return isDataEnabled();
}
/**
@@ -6396,22 +6401,28 @@
* {@link ConnectivityManager#getRestrictBackgroundStatus}.
*
* @return true if mobile data is enabled.
- *
- * @deprecated use {@link #isUserMobileDataEnabled()} instead.
*/
- @Deprecated
public boolean isDataEnabled() {
- return isUserMobileDataEnabled();
+ return getDataEnabled(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
}
/**
- * @deprecated use {@link #isUserMobileDataEnabled()} instead.
+ * @deprecated use {@link #isDataEnabled()} instead.
* @hide
*/
@Deprecated
@SystemApi
public boolean getDataEnabled(int subId) {
- return isUserMobileDataEnabled(subId);
+ boolean retVal = false;
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null)
+ retVal = telephony.isUserDataEnabled(subId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#isUserDataEnabled", e);
+ } catch (NullPointerException e) {
+ }
+ return retVal;
}
/** @hide */
@@ -7684,56 +7695,12 @@
}
/**
- * Turns mobile data on or off.
- * If the {@link TelephonyManager} object has been created with
- * {@link #createForSubscriptionId}, this API applies to the given subId.
- * Otherwise, it applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
- *
- * <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
- * app has carrier privileges (see {@link #hasCarrierPrivileges}.
- *
- * @param enable Whether to enable mobile data.
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public void setUserMobileDataEnabled(boolean enable) {
- setUserMobileDataEnabled(
- getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enable);
- }
-
- /**
- * Returns whether mobile data is enabled or not per user setting. There are other factors
- * that could disable mobile data, but they are not considered here.
- *
- * If this object has been created with {@link #createForSubscriptionId}, applies to the given
- * subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
- *
- * <p>Requires one of the following permissions:
- * {@link android.Manifest.permission#ACCESS_NETWORK_STATE ACCESS_NETWORK_STATE},
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}, or that the
- * calling app has carrier privileges (see {@link #hasCarrierPrivileges}.
- *
- * <p>Note that this does not take into account any data restrictions that may be present on the
- * calling app. Such restrictions may be inspected with
- * {@link ConnectivityManager#getRestrictBackgroundStatus}.
- *
- * @return true if mobile data is enabled.
- */
- @RequiresPermission(anyOf = {
- android.Manifest.permission.ACCESS_NETWORK_STATE,
- android.Manifest.permission.MODIFY_PHONE_STATE
- })
- public boolean isUserMobileDataEnabled() {
- return isUserMobileDataEnabled(
- getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
- }
-
- /**
* @hide
- * Unlike isUserMobileDataEnabled, this API also evaluates carrierDataEnabled,
- * policyDataEnabled etc to give a final decision.
+ * It's similar to isDataEnabled, but unlike isDataEnabled, this API also evaluates
+ * carrierDataEnabled, policyDataEnabled etc to give a final decision of whether mobile data is
+ * capable of using.
*/
- public boolean isMobileDataEnabled() {
+ public boolean isDataCapable() {
boolean retVal = false;
try {
int subId = getSubId(SubscriptionManager.getDefaultDataSubscriptionId());
@@ -7748,35 +7715,6 @@
}
/**
- * Utility class of {@link #isUserMobileDataEnabled()};
- */
- private boolean isUserMobileDataEnabled(int subId) {
- boolean retVal = false;
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null)
- retVal = telephony.isUserDataEnabled(subId);
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#isUserDataEnabled", e);
- } catch (NullPointerException e) {
- }
- return retVal;
- }
-
- /** Utility method of {@link #setUserMobileDataEnabled(boolean)} */
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- private void setUserMobileDataEnabled(int subId, boolean enable) {
- try {
- Log.d(TAG, "setUserMobileDataEnabled: enabled=" + enable);
- ITelephony telephony = getITelephony();
- if (telephony != null)
- telephony.setUserDataEnabled(subId, enable);
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#setUserDataEnabled", e);
- }
- }
-
- /**
* In this mode, modem will not send specified indications when screen is off.
* @hide
*/
diff --git a/telephony/java/android/telephony/euicc/DownloadableSubscription.java b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
index 88db22b..edf3b08 100644
--- a/telephony/java/android/telephony/euicc/DownloadableSubscription.java
+++ b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
@@ -17,6 +17,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.app.PendingIntent;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.UiccAccessRule;
@@ -26,7 +27,14 @@
import com.android.internal.util.Preconditions;
-/** Information about a subscription which is available for download. */
+/**
+ * Information about a subscription which is downloadable to an eUICC using
+ * {@link EuiccManager#downloadSubscription(DownloadableSubscription, boolean, PendingIntent).
+ *
+ * <p>For example, a DownloadableSubscription can be created through an activation code parsed from
+ * a QR code. A server address can be parsed from the activation code to download more information
+ * about the profile, such as carrier name, access rules, etc.
+ */
public final class DownloadableSubscription implements Parcelable {
public static final Creator<DownloadableSubscription> CREATOR =
@@ -136,7 +144,15 @@
/**
* Create a DownloadableSubscription for the given activation code.
*
- * @param encodedActivationCode the activation code to use. Must not be null.
+ * <p>This fills the encodedActivationCode field. Other fields like confirmationCode,
+ * carrierName and accessRules may be filled in the implementation of
+ * {@code android.service.euicc.EuiccService} if exists.
+ *
+ * @param encodedActivationCode the activation code to use. An activation code can be parsed
+ * from a user scanned QR code. The format of activation code is defined in SGP.22. For
+ * example, "1$SMDP.GSMA.COM$04386-AGYFT-A74Y8-3F815$1.3.6.1.4.1.31746". For detail, see
+ * {@code com.android.euicc.data.ActivationCode}. Must not be null.
+ *
* @return the {@link DownloadableSubscription} which may be passed to
* {@link EuiccManager#downloadSubscription}.
*/
@@ -157,6 +173,9 @@
/**
* Returns the confirmation code.
+ *
+ * <p>As an example, the confirmation code can be input by the user through a carrier app or the
+ * UI component of the eUICC local profile assistant (LPA) application.
*/
@Nullable
public String getConfirmationCode() {
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index dff1c6f..b732d4d 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -142,11 +142,9 @@
"android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE";
/**
- * Key for an extra set on {@link #getDownloadableSubscriptionMetadata} PendingIntent result
+ * Key for an extra set on {@code #getDownloadableSubscriptionMetadata} PendingIntent result
* callbacks providing the downloadable subscription metadata.
- * @hide
*/
- @SystemApi
public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION =
"android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION";
diff --git a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
index 8b81b0d..bcad554 100644
--- a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
@@ -26,6 +26,7 @@
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
@@ -49,10 +50,11 @@
/**
* Handle preinstalled carrier apps which should be disabled until a matching SIM is inserted.
*
- * Evaluates the list of applications in config_disabledUntilUsedPreinstalledCarrierApps. We
- * want to disable each such application which is present on the system image until the user
- * inserts a SIM which causes that application to gain carrier privilege (indicating a "match"),
- * without interfering with the user if they opt to enable/disable the app explicitly.
+ * Evaluates the list of applications in
+ * {@link SystemConfig#getDisabledUntilUsedPreinstalledCarrierApps()}. We want to disable each
+ * such application which is present on the system image until the user inserts a SIM which
+ * causes that application to gain carrier privilege (indicating a "match"), without interfering
+ * with the user if they opt to enable/disable the app explicitly.
*
* So, for each such app, we either disable until used IFF the app is not carrier privileged AND
* in the default state (e.g. not explicitly DISABLED/DISABLED_BY_USER/ENABLED), or we enable if
@@ -76,8 +78,8 @@
Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
}
SystemConfig config = SystemConfig.getInstance();
- String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray(
- com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps);
+ ArraySet<String> systemCarrierAppsDisabledUntilUsed =
+ config.getDisabledUntilUsedPreinstalledCarrierApps();
ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed =
config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
disableCarrierAppsUntilPrivileged(callingPackage, packageManager, telephonyManager,
@@ -102,8 +104,10 @@
Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
}
SystemConfig config = SystemConfig.getInstance();
- String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray(
- com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps);
+ ArraySet<String> systemCarrierAppsDisabledUntilUsed =
+ config.getDisabledUntilUsedPreinstalledCarrierApps();
+
+
ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed =
config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
disableCarrierAppsUntilPrivileged(callingPackage, packageManager,
@@ -116,7 +120,7 @@
public static void disableCarrierAppsUntilPrivileged(String callingPackage,
IPackageManager packageManager, @Nullable TelephonyManager telephonyManager,
ContentResolver contentResolver, int userId,
- String[] systemCarrierAppsDisabledUntilUsed,
+ ArraySet<String> systemCarrierAppsDisabledUntilUsed,
ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed) {
List<ApplicationInfo> candidates = getDefaultCarrierAppCandidatesHelper(packageManager,
userId, systemCarrierAppsDisabledUntilUsed);
@@ -286,8 +290,8 @@
*/
public static List<ApplicationInfo> getDefaultCarrierAppCandidates(
IPackageManager packageManager, int userId) {
- String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray(
- com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps);
+ ArraySet<String> systemCarrierAppsDisabledUntilUsed =
+ SystemConfig.getInstance().getDisabledUntilUsedPreinstalledCarrierApps();
return getDefaultCarrierAppCandidatesHelper(packageManager, userId,
systemCarrierAppsDisabledUntilUsed);
}
@@ -295,14 +299,19 @@
private static List<ApplicationInfo> getDefaultCarrierAppCandidatesHelper(
IPackageManager packageManager,
int userId,
- String[] systemCarrierAppsDisabledUntilUsed) {
- if (systemCarrierAppsDisabledUntilUsed == null
- || systemCarrierAppsDisabledUntilUsed.length == 0) {
+ ArraySet<String> systemCarrierAppsDisabledUntilUsed) {
+ if (systemCarrierAppsDisabledUntilUsed == null) {
return null;
}
- List<ApplicationInfo> apps = new ArrayList<>(systemCarrierAppsDisabledUntilUsed.length);
- for (int i = 0; i < systemCarrierAppsDisabledUntilUsed.length; i++) {
- String packageName = systemCarrierAppsDisabledUntilUsed[i];
+
+ int size = systemCarrierAppsDisabledUntilUsed.size();
+ if (size == 0) {
+ return null;
+ }
+
+ List<ApplicationInfo> apps = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ String packageName = systemCarrierAppsDisabledUntilUsed.valueAt(i);
ApplicationInfo ai =
getApplicationInfoIfSystemApp(packageManager, userId, packageName);
if (ai != null) {
diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java
index c866371..941c94d 100644
--- a/tests/net/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java
@@ -315,28 +315,26 @@
@Test
public void testEqualsNetCapabilities() {
- int CAPABILITY = NET_CAPABILITY_MMS; // An arbitrary not mutable capability.
-
NetworkCapabilities nc1 = new NetworkCapabilities();
NetworkCapabilities nc2 = new NetworkCapabilities();
assertTrue(nc1.equalsNetCapabilities(nc2));
assertEquals(nc1, nc2);
- nc1.addCapability(CAPABILITY);
+ nc1.addCapability(NET_CAPABILITY_MMS);
assertFalse(nc1.equalsNetCapabilities(nc2));
assertNotEquals(nc1, nc2);
- nc2.addCapability(CAPABILITY);
+ nc2.addCapability(NET_CAPABILITY_MMS);
assertTrue(nc1.equalsNetCapabilities(nc2));
assertEquals(nc1, nc2);
- nc1.addUnwantedCapability(CAPABILITY);
+ nc1.addUnwantedCapability(NET_CAPABILITY_INTERNET);
assertFalse(nc1.equalsNetCapabilities(nc2));
- nc2.addUnwantedCapability(CAPABILITY);
+ nc2.addUnwantedCapability(NET_CAPABILITY_INTERNET);
assertTrue(nc1.equalsNetCapabilities(nc2));
- nc1.removeCapability(CAPABILITY);
+ nc1.removeCapability(NET_CAPABILITY_INTERNET);
assertFalse(nc1.equalsNetCapabilities(nc2));
- nc2.removeCapability(CAPABILITY);
+ nc2.removeCapability(NET_CAPABILITY_INTERNET);
assertTrue(nc1.equalsNetCapabilities(nc2));
}
diff --git a/tools/stringslint/stringslint_sha.sh b/tools/stringslint/stringslint_sha.sh
index c79ba04..bd80bb4 100755
--- a/tools/stringslint/stringslint_sha.sh
+++ b/tools/stringslint/stringslint_sha.sh
@@ -1,4 +1,5 @@
#!/bin/bash
+LOCAL_DIR="$( dirname ${BASH_SOURCE} )"
git show --name-only --pretty=format: $1 | grep values/strings.xml | while read file; do
- python $ANDROID_BUILD_TOP/frameworks/base/tools/stringslint/stringslint.py <(git show $1:$file) <(git show $1^:$file)
+ python $LOCAL_DIR/stringslint.py <(git show $1:$file) <(git show $1^:$file)
done