diff options
265 files changed, 6998 insertions, 2997 deletions
diff --git a/Android.mk b/Android.mk index bd8b16a8ea1f..b71f08c98dfb 100644 --- a/Android.mk +++ b/Android.mk @@ -197,6 +197,7 @@ LOCAL_SRC_FILES += \ core/java/android/os/IBatteryPropertiesListener.aidl \ core/java/android/os/IBatteryPropertiesRegistrar.aidl \ core/java/android/os/ICancellationSignal.aidl \ + core/java/android/os/IDeviceIdleController.aidl \ core/java/android/os/IMessenger.aidl \ core/java/android/os/INetworkActivityListener.aidl \ core/java/android/os/INetworkManagementService.aidl \ diff --git a/api/current.txt b/api/current.txt index f332599ef5ae..0aeda1c6876e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -23,8 +23,10 @@ package android { field public static final java.lang.String BIND_CARRIER_CONFIG_SERVICE = "android.permission.BIND_CARRIER_CONFIG_SERVICE"; field public static final java.lang.String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE"; field public static final java.lang.String BIND_CHOOSER_TARGET_SERVICE = "android.permission.BIND_CHOOSER_TARGET_SERVICE"; + field public static final java.lang.String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE"; field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN"; field public static final java.lang.String BIND_DREAM_SERVICE = "android.permission.BIND_DREAM_SERVICE"; + field public static final java.lang.String BIND_INCALL_SERVICE = "android.permission.BIND_INCALL_SERVICE"; field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD"; field public static final java.lang.String BIND_MEDIA_ROUTE_SERVICE = "android.permission.BIND_MEDIA_ROUTE_SERVICE"; field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE"; @@ -278,7 +280,7 @@ package android { field public static final int allowParallelSyncs = 16843570; // 0x1010332 field public static final int allowSingleTap = 16843353; // 0x1010259 field public static final int allowTaskReparenting = 16843268; // 0x1010204 - field public static final int allowUndo = 16844006; // 0x10104e6 + field public static final int allowUndo = 16844005; // 0x10104e5 field public static final int alpha = 16843551; // 0x101031f field public static final int alphabeticShortcut = 16843235; // 0x10101e3 field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef @@ -299,7 +301,7 @@ package android { field public static final int anyDensity = 16843372; // 0x101026c field public static final int apduServiceBanner = 16843757; // 0x10103ed field public static final int apiKey = 16843281; // 0x1010211 - field public static final int assistBlocked = 16844020; // 0x10104f4 + field public static final int assistBlocked = 16844019; // 0x10104f3 field public static final int author = 16843444; // 0x10102b4 field public static final int authorities = 16842776; // 0x1010018 field public static final int autoAdvanceViewId = 16843535; // 0x101030f @@ -310,7 +312,7 @@ package android { field public static final int autoStart = 16843445; // 0x10102b5 field public static final deprecated int autoText = 16843114; // 0x101016a field public static final int autoUrlDetect = 16843404; // 0x101028c - field public static final int autoVerify = 16844010; // 0x10104ea + field public static final int autoVerify = 16844009; // 0x10104e9 field public static final int background = 16842964; // 0x10100d4 field public static final int backgroundDimAmount = 16842802; // 0x1010032 field public static final int backgroundDimEnabled = 16843295; // 0x101021f @@ -334,7 +336,7 @@ package android { field public static final int bottomRightRadius = 16843180; // 0x10101ac field public static final int breadCrumbShortTitle = 16843524; // 0x1010304 field public static final int breadCrumbTitle = 16843523; // 0x1010303 - field public static final int breakStrategy = 16844011; // 0x10104eb + field public static final int breakStrategy = 16844010; // 0x10104ea field public static final int bufferType = 16843086; // 0x101014e field public static final int button = 16843015; // 0x1010107 field public static final int buttonBarButtonStyle = 16843567; // 0x101032f @@ -396,7 +398,7 @@ package android { field public static final int colorActivatedHighlight = 16843664; // 0x1010390 field public static final int colorBackground = 16842801; // 0x1010031 field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab - field public static final int colorBackgroundFloating = 16844007; // 0x10104e7 + field public static final int colorBackgroundFloating = 16844006; // 0x10104e6 field public static final int colorButtonNormal = 16843819; // 0x101042b field public static final int colorControlActivated = 16843818; // 0x101042a field public static final int colorControlHighlight = 16843820; // 0x101042c @@ -505,7 +507,7 @@ package android { field public static final int dropDownWidth = 16843362; // 0x1010262 field public static final int duplicateParentState = 16842985; // 0x10100e9 field public static final int duration = 16843160; // 0x1010198 - field public static final int dynamicResources = 16844019; // 0x10104f3 + field public static final int dynamicResources = 16844018; // 0x10104f2 field public static final int editTextBackground = 16843602; // 0x1010352 field public static final int editTextColor = 16843601; // 0x1010351 field public static final int editTextPreferenceStyle = 16842898; // 0x1010092 @@ -517,7 +519,7 @@ package android { field public static final int ellipsize = 16842923; // 0x10100ab field public static final int ems = 16843096; // 0x1010158 field public static final int enabled = 16842766; // 0x101000e - field public static final int end = 16843997; // 0x10104dd + field public static final int end = 16843996; // 0x10104dc field public static final int endColor = 16843166; // 0x101019e field public static final deprecated int endYear = 16843133; // 0x101017d field public static final int enterFadeDuration = 16843532; // 0x101030c @@ -539,7 +541,7 @@ package android { field public static final int expandableListViewWhiteStyle = 16843446; // 0x10102b6 field public static final int exported = 16842768; // 0x1010010 field public static final int extraTension = 16843371; // 0x101026b - field public static final int extractNativeLibs = 16844008; // 0x10104e8 + field public static final int extractNativeLibs = 16844007; // 0x10104e7 field public static final int factor = 16843219; // 0x10101d3 field public static final int fadeDuration = 16843384; // 0x1010278 field public static final int fadeEnabled = 16843390; // 0x101027e @@ -653,8 +655,8 @@ package android { field public static final int host = 16842792; // 0x1010028 field public static final int icon = 16842754; // 0x1010002 field public static final int iconPreview = 16843337; // 0x1010249 - field public static final int iconTint = 16844000; // 0x10104e0 - field public static final int iconTintMode = 16844001; // 0x10104e1 + field public static final int iconTint = 16843999; // 0x10104df + field public static final int iconTintMode = 16844000; // 0x10104e0 field public static final int iconifiedByDefault = 16843514; // 0x10102fa field public static final int id = 16842960; // 0x10100d0 field public static final int ignoreGravity = 16843263; // 0x10101ff @@ -794,7 +796,7 @@ package android { field public static final int layout_x = 16843135; // 0x101017f field public static final int layout_y = 16843136; // 0x1010180 field public static final int left = 16843181; // 0x10101ad - field public static final int leftIndents = 16844016; // 0x10104f0 + field public static final int leftIndents = 16844015; // 0x10104ef field public static final int letterSpacing = 16843958; // 0x10104b6 field public static final int lineSpacingExtra = 16843287; // 0x1010217 field public static final int lineSpacingMultiplier = 16843288; // 0x1010218 @@ -817,7 +819,7 @@ package android { field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208 field public static final int listViewStyle = 16842868; // 0x1010074 field public static final int listViewWhiteStyle = 16842869; // 0x1010075 - field public static final int lockTaskMode = 16844015; // 0x10104ef + field public static final int lockTaskMode = 16844014; // 0x10104ee field public static final int logo = 16843454; // 0x10102be field public static final int longClickable = 16842982; // 0x10100e6 field public static final int loopViews = 16843527; // 0x1010307 @@ -866,8 +868,8 @@ package android { field public static final int navigationContentDescription = 16843969; // 0x10104c1 field public static final int navigationIcon = 16843968; // 0x10104c0 field public static final int navigationMode = 16843471; // 0x10102cf - field public static final int navigationTint = 16844004; // 0x10104e4 - field public static final int navigationTintMode = 16844005; // 0x10104e5 + field public static final int navigationTint = 16844003; // 0x10104e3 + field public static final int navigationTintMode = 16844004; // 0x10104e4 field public static final int negativeButtonText = 16843254; // 0x10101f6 field public static final int nestedScrollingEnabled = 16843830; // 0x1010436 field public static final int nextFocusDown = 16842980; // 0x10100e4 @@ -881,7 +883,7 @@ package android { field public static final int numColumns = 16843032; // 0x1010118 field public static final int numStars = 16843076; // 0x1010144 field public static final int numbersBackgroundColor = 16843938; // 0x10104a2 - field public static final int numbersInnerTextColor = 16843999; // 0x10104df + field public static final int numbersInnerTextColor = 16843998; // 0x10104de field public static final int numbersSelectorColor = 16843939; // 0x10104a3 field public static final int numbersTextColor = 16843937; // 0x10104a1 field public static final deprecated int numeric = 16843109; // 0x1010165 @@ -899,8 +901,8 @@ package android { field public static final int overScrollFooter = 16843459; // 0x10102c3 field public static final int overScrollHeader = 16843458; // 0x10102c2 field public static final int overScrollMode = 16843457; // 0x10102c1 - field public static final int overflowTint = 16844002; // 0x10104e2 - field public static final int overflowTintMode = 16844003; // 0x10104e3 + field public static final int overflowTint = 16844001; // 0x10104e1 + field public static final int overflowTintMode = 16844002; // 0x10104e2 field public static final int overlapAnchor = 16843874; // 0x1010462 field public static final int overridesImplicitlyEnabledSubtype = 16843682; // 0x10103a2 field public static final int packageNames = 16843649; // 0x1010381 @@ -995,7 +997,7 @@ package android { field public static final int readPermission = 16842759; // 0x1010007 field public static final int recognitionService = 16843932; // 0x101049c field public static final int relinquishTaskIdentity = 16843894; // 0x1010476 - field public static final int removeBeforeMRelease = 16844014; // 0x10104ee + field public static final int removeBeforeMRelease = 16844013; // 0x10104ed field public static final int reparent = 16843964; // 0x10104bc field public static final int reparentWithOverlay = 16843965; // 0x10104bd field public static final int repeatCount = 16843199; // 0x10101bf @@ -1014,7 +1016,6 @@ package android { field public static final int resizeClip = 16843983; // 0x10104cf field public static final int resizeMode = 16843619; // 0x1010363 field public static final int resizeable = 16843405; // 0x101028d - field public static final int resizeableActivity = 16843995; // 0x10104db field public static final int resource = 16842789; // 0x1010025 field public static final int restoreAnyVersion = 16843450; // 0x10102ba field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d @@ -1024,7 +1025,7 @@ package android { field public static final int reversible = 16843851; // 0x101044b field public static final int revisionCode = 16843989; // 0x10104d5 field public static final int right = 16843183; // 0x10101af - field public static final int rightIndents = 16844017; // 0x10104f1 + field public static final int rightIndents = 16844016; // 0x10104f0 field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093 field public static final int ringtoneType = 16843257; // 0x10101f9 field public static final int rotation = 16843558; // 0x1010326 @@ -1100,7 +1101,7 @@ package android { field public static final int showAsAction = 16843481; // 0x10102d9 field public static final int showDefault = 16843258; // 0x10101fa field public static final int showDividers = 16843561; // 0x1010329 - field public static final int showForAllUsers = 16844018; // 0x10104f2 + field public static final int showForAllUsers = 16844017; // 0x10104f1 field public static final deprecated int showOnLockScreen = 16843721; // 0x10103c9 field public static final int showSilent = 16843259; // 0x10101fb field public static final int showText = 16843949; // 0x10104ad @@ -1130,7 +1131,7 @@ package android { field public static final int stackFromBottom = 16843005; // 0x10100fd field public static final int stackViewStyle = 16843838; // 0x101043e field public static final int starStyle = 16842882; // 0x1010082 - field public static final int start = 16843996; // 0x10104dc + field public static final int start = 16843995; // 0x10104db field public static final int startColor = 16843165; // 0x101019d field public static final int startDelay = 16843746; // 0x10103e2 field public static final int startOffset = 16843198; // 0x10101be @@ -1186,7 +1187,7 @@ package android { field public static final int summaryColumn = 16843426; // 0x10102a2 field public static final int summaryOff = 16843248; // 0x10101f0 field public static final int summaryOn = 16843247; // 0x10101ef - field public static final int supportsAssistGesture = 16844012; // 0x10104ec + field public static final int supportsAssistGesture = 16844011; // 0x10104eb field public static final int supportsRtl = 16843695; // 0x10103af field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb field public static final int supportsUploading = 16843419; // 0x101029b @@ -1287,7 +1288,7 @@ package android { field public static final int thicknessRatio = 16843164; // 0x101019c field public static final int thumb = 16843074; // 0x1010142 field public static final int thumbOffset = 16843075; // 0x1010143 - field public static final int thumbPosition = 16844013; // 0x10104ed + field public static final int thumbPosition = 16844012; // 0x10104ec field public static final int thumbTextPadding = 16843634; // 0x1010372 field public static final int thumbTint = 16843889; // 0x1010471 field public static final int thumbTintMode = 16843890; // 0x1010472 @@ -1351,7 +1352,7 @@ package android { field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310 field public static final int useLevel = 16843167; // 0x101019f field public static final int userVisible = 16843409; // 0x1010291 - field public static final int usesCleartextTraffic = 16844009; // 0x10104e9 + field public static final int usesCleartextTraffic = 16844008; // 0x10104e8 field public static final int value = 16842788; // 0x1010024 field public static final int valueFrom = 16843486; // 0x10102de field public static final int valueTo = 16843487; // 0x10102df @@ -1416,10 +1417,10 @@ package android { field public static final int windowExitTransition = 16843832; // 0x1010438 field public static final int windowFrame = 16842837; // 0x1010055 field public static final int windowFullscreen = 16843277; // 0x101020d - field public static final int windowLightStatusBar = 16843998; // 0x10104de field public static final int windowHideAnimation = 16842935; // 0x10100b7 field public static final int windowIsFloating = 16842839; // 0x1010057 field public static final int windowIsTranslucent = 16842840; // 0x1010058 + field public static final int windowLightStatusBar = 16843997; // 0x10104dd field public static final int windowMinWidthMajor = 16843606; // 0x1010356 field public static final int windowMinWidthMinor = 16843607; // 0x1010357 field public static final int windowNoDisplay = 16843294; // 0x101021e @@ -5729,6 +5730,7 @@ package android.app.admin { method public int getPasswordMinimumSymbols(android.content.ComponentName); method public int getPasswordMinimumUpperCase(android.content.ComponentName); method public int getPasswordQuality(android.content.ComponentName); + method public int getPermissionPolicy(android.content.ComponentName); method public java.util.List<java.lang.String> getPermittedAccessibilityServices(android.content.ComponentName); method public java.util.List<java.lang.String> getPermittedInputMethods(android.content.ComponentName); method public boolean getScreenCaptureDisabled(android.content.ComponentName); @@ -5781,6 +5783,8 @@ package android.app.admin { method public void setPasswordMinimumSymbols(android.content.ComponentName, int); method public void setPasswordMinimumUpperCase(android.content.ComponentName, int); method public void setPasswordQuality(android.content.ComponentName, int); + method public boolean setPermissionGranted(android.content.ComponentName, java.lang.String, java.lang.String, boolean); + method public void setPermissionPolicy(android.content.ComponentName, int); method public boolean setPermittedAccessibilityServices(android.content.ComponentName, java.util.List<java.lang.String>); method public boolean setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>); method public void setPreferredSetupActivity(android.content.ComponentName, android.content.ComponentName); @@ -5869,6 +5873,9 @@ package android.app.admin { field public static final int PASSWORD_QUALITY_NUMERIC_COMPLEX = 196608; // 0x30000 field public static final int PASSWORD_QUALITY_SOMETHING = 65536; // 0x10000 field public static final int PASSWORD_QUALITY_UNSPECIFIED = 0; // 0x0 + field public static final int PERMISSION_POLICY_AUTO_DENY = 2; // 0x2 + field public static final int PERMISSION_POLICY_AUTO_GRANT = 1; // 0x1 + field public static final int PERMISSION_POLICY_PROMPT = 0; // 0x0 field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1 field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1 field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 @@ -9402,6 +9409,7 @@ package android.content.pm { field public static final int GET_SIGNATURES = 64; // 0x40 field public static final int GET_UNINSTALLED_PACKAGES = 8192; // 0x2000 field public static final int GET_URI_PERMISSION_PATTERNS = 2048; // 0x800 + field public static final int MATCH_ALL = 131072; // 0x20000 field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000 field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L field public static final int PERMISSION_DENIED = -1; // 0xffffffff @@ -14017,6 +14025,7 @@ package android.hardware.usb { method public java.lang.String getProductName(); method public java.lang.String getSerialNumber(); method public int getVendorId(); + method public java.lang.String getVersion(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.hardware.usb.UsbDevice> CREATOR; } @@ -17258,6 +17267,7 @@ package android.media.midi { field public static final java.lang.String PROPERTY_PRODUCT = "product"; field public static final java.lang.String PROPERTY_SERIAL_NUMBER = "serial_number"; field public static final java.lang.String PROPERTY_USB_DEVICE = "usb_device"; + field public static final java.lang.String PROPERTY_VERSION = "version"; field public static final int TYPE_BLUETOOTH = 3; // 0x3 field public static final int TYPE_USB = 1; // 0x1 field public static final int TYPE_VIRTUAL = 2; // 0x2 @@ -28527,10 +28537,9 @@ package android.security { method public java.lang.String getKeystoreAlias(); method public int getPurposes(); method public int getUserAuthenticationValidityDurationSeconds(); - method public int getUserAuthenticators(); method public boolean isEncryptionRequired(); - method public boolean isInvalidatedOnNewFingerprintEnrolled(); method public boolean isRandomizedEncryptionRequired(); + method public boolean isUserAuthenticationRequired(); } public static class KeyGeneratorSpec.Builder { @@ -28540,7 +28549,6 @@ package android.security { method public android.security.KeyGeneratorSpec.Builder setBlockModes(java.lang.String...); method public android.security.KeyGeneratorSpec.Builder setEncryptionPaddings(java.lang.String...); method public android.security.KeyGeneratorSpec.Builder setEncryptionRequired(boolean); - method public android.security.KeyGeneratorSpec.Builder setInvalidatedOnNewFingerprintEnrolled(boolean); method public android.security.KeyGeneratorSpec.Builder setKeySize(int); method public android.security.KeyGeneratorSpec.Builder setKeyValidityEnd(java.util.Date); method public android.security.KeyGeneratorSpec.Builder setKeyValidityForConsumptionEnd(java.util.Date); @@ -28548,8 +28556,8 @@ package android.security { method public android.security.KeyGeneratorSpec.Builder setKeyValidityStart(java.util.Date); method public android.security.KeyGeneratorSpec.Builder setPurposes(int); method public android.security.KeyGeneratorSpec.Builder setRandomizedEncryptionRequired(boolean); + method public android.security.KeyGeneratorSpec.Builder setUserAuthenticationRequired(boolean); method public android.security.KeyGeneratorSpec.Builder setUserAuthenticationValidityDurationSeconds(int); - method public android.security.KeyGeneratorSpec.Builder setUserAuthenticators(int); } public class KeyNotYetValidException extends java.security.InvalidKeyException { @@ -28577,10 +28585,9 @@ package android.security { method public java.util.Date getStartDate(); method public javax.security.auth.x500.X500Principal getSubjectDN(); method public int getUserAuthenticationValidityDurationSeconds(); - method public int getUserAuthenticators(); method public boolean isEncryptionRequired(); - method public boolean isInvalidatedOnNewFingerprintEnrolled(); method public boolean isRandomizedEncryptionRequired(); + method public boolean isUserAuthenticationRequired(); } public static final class KeyPairGeneratorSpec.Builder { @@ -28593,7 +28600,6 @@ package android.security { method public android.security.KeyPairGeneratorSpec.Builder setEncryptionPaddings(java.lang.String...); method public android.security.KeyPairGeneratorSpec.Builder setEncryptionRequired(); method public android.security.KeyPairGeneratorSpec.Builder setEndDate(java.util.Date); - method public android.security.KeyPairGeneratorSpec.Builder setInvalidatedOnNewFingerprintEnrolled(boolean); method public android.security.KeyPairGeneratorSpec.Builder setKeySize(int); method public android.security.KeyPairGeneratorSpec.Builder setKeyType(java.lang.String) throws java.security.NoSuchAlgorithmException; method public android.security.KeyPairGeneratorSpec.Builder setKeyValidityEnd(java.util.Date); @@ -28606,8 +28612,8 @@ package android.security { method public android.security.KeyPairGeneratorSpec.Builder setSignaturePaddings(java.lang.String...); method public android.security.KeyPairGeneratorSpec.Builder setStartDate(java.util.Date); method public android.security.KeyPairGeneratorSpec.Builder setSubject(javax.security.auth.x500.X500Principal); + method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticationRequired(boolean); method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticationValidityDurationSeconds(int); - method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticators(int); } public abstract class KeyStoreKeyProperties { @@ -28632,14 +28638,6 @@ package android.security { public static abstract class KeyStoreKeyProperties.PurposeEnum implements java.lang.annotation.Annotation { } - public static abstract class KeyStoreKeyProperties.UserAuthenticator { - field public static final int FINGERPRINT_READER = 2; // 0x2 - field public static final int LOCK_SCREEN = 1; // 0x1 - } - - public static abstract class KeyStoreKeyProperties.UserAuthenticatorEnum implements java.lang.annotation.Annotation { - } - public class KeyStoreKeySpec implements java.security.spec.KeySpec { method public java.lang.String[] getBlockModes(); method public java.lang.String[] getDigests(); @@ -28652,15 +28650,15 @@ package android.security { method public int getOrigin(); method public int getPurposes(); method public java.lang.String[] getSignaturePaddings(); - method public int getTeeEnforcedUserAuthenticators(); method public int getUserAuthenticationValidityDurationSeconds(); - method public int getUserAuthenticators(); - method public boolean isInvalidatedOnNewFingerprintEnrolled(); method public boolean isTeeBacked(); + method public boolean isUserAuthenticationRequired(); + method public boolean isUserAuthenticationRequirementTeeEnforced(); } public final class KeyStoreParameter implements java.security.KeyStore.ProtectionParameter { method public java.lang.String[] getBlockModes(); + method public android.content.Context getContext(); method public java.lang.String[] getDigests(); method public java.lang.String[] getEncryptionPaddings(); method public java.util.Date getKeyValidityForConsumptionEnd(); @@ -28669,11 +28667,10 @@ package android.security { method public int getPurposes(); method public java.lang.String[] getSignaturePaddings(); method public int getUserAuthenticationValidityDurationSeconds(); - method public int getUserAuthenticators(); method public boolean isDigestsSpecified(); method public boolean isEncryptionRequired(); - method public boolean isInvalidatedOnNewFingerprintEnrolled(); method public boolean isRandomizedEncryptionRequired(); + method public boolean isUserAuthenticationRequired(); } public static final class KeyStoreParameter.Builder { @@ -28683,7 +28680,6 @@ package android.security { method public android.security.KeyStoreParameter.Builder setDigests(java.lang.String...); method public android.security.KeyStoreParameter.Builder setEncryptionPaddings(java.lang.String...); method public android.security.KeyStoreParameter.Builder setEncryptionRequired(boolean); - method public android.security.KeyStoreParameter.Builder setInvalidatedOnNewFingerprintEnrolled(boolean); method public android.security.KeyStoreParameter.Builder setKeyValidityEnd(java.util.Date); method public android.security.KeyStoreParameter.Builder setKeyValidityForConsumptionEnd(java.util.Date); method public android.security.KeyStoreParameter.Builder setKeyValidityForOriginationEnd(java.util.Date); @@ -28691,8 +28687,8 @@ package android.security { method public android.security.KeyStoreParameter.Builder setPurposes(int); method public android.security.KeyStoreParameter.Builder setRandomizedEncryptionRequired(boolean); method public android.security.KeyStoreParameter.Builder setSignaturePaddings(java.lang.String...); + method public android.security.KeyStoreParameter.Builder setUserAuthenticationRequired(boolean); method public android.security.KeyStoreParameter.Builder setUserAuthenticationValidityDurationSeconds(int); - method public android.security.KeyStoreParameter.Builder setUserAuthenticators(int); } public class NetworkSecurityPolicy { @@ -29207,6 +29203,7 @@ package android.speech { field public static final java.lang.String EXTRA_ONLY_RETURN_LANGUAGE_PREFERENCE = "android.speech.extra.ONLY_RETURN_LANGUAGE_PREFERENCE"; field public static final java.lang.String EXTRA_ORIGIN = "android.speech.extra.ORIGIN"; field public static final java.lang.String EXTRA_PARTIAL_RESULTS = "android.speech.extra.PARTIAL_RESULTS"; + field public static final java.lang.String EXTRA_PREFER_OFFLINE = "android.speech.extra.PREFER_OFFLINE"; field public static final java.lang.String EXTRA_PROMPT = "android.speech.extra.PROMPT"; field public static final java.lang.String EXTRA_RESULTS = "android.speech.extra.RESULTS"; field public static final java.lang.String EXTRA_RESULTS_PENDINGINTENT = "android.speech.extra.RESULTS_PENDINGINTENT"; @@ -30433,7 +30430,6 @@ package android.telecom { public static abstract class InCallService.VideoCall { ctor public InCallService.VideoCall(); method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback); - method public abstract void unregisterCallback(); method public abstract void requestCallDataUsage(); method public abstract void requestCameraCapabilities(); method public abstract void sendSessionModifyRequest(android.telecom.VideoProfile); @@ -30444,6 +30440,7 @@ package android.telecom { method public abstract void setPauseImage(java.lang.String); method public abstract void setPreviewSurface(android.view.Surface); method public abstract void setZoom(float); + method public abstract void unregisterCallback(); } public static abstract class InCallService.VideoCall.Callback { @@ -30688,11 +30685,34 @@ package android.telephony { method public android.os.Bundle getConfigForSubId(int); method public void reloadCarrierConfigForSubId(int); field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED"; + field public static final java.lang.String BOOL_ADDITIONAL_CALL_SETTING = "bool_additional_call_setting"; + field public static final java.lang.String BOOL_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG = "bool_allow_emergency_numbers_in_call_log"; + field public static final java.lang.String BOOL_ALLOW_LOCAL_DTMF_TONES = "bool_allow_local_dtmf_tones"; field public static final java.lang.String BOOL_APN_EXPAND = "bool_apn_expand"; + field public static final java.lang.String BOOL_AUTO_RETRY_ENABLED = "bool_auto_retry_enabled"; + field public static final java.lang.String BOOL_CARRIER_SETTINGS_ENABLE = "bool_carrier_settings_enable"; field public static final java.lang.String BOOL_CARRIER_VOLTE_AVAILABLE = "bool_carrier_volte_available"; field public static final java.lang.String BOOL_CARRIER_VOLTE_PROVISIONED = "bool_carrier_volte_provisioned"; field public static final java.lang.String BOOL_CARRIER_VOLTE_TTY_SUPPORTED = "bool_carrier_volte_tty_supported"; + field public static final java.lang.String BOOL_DISABLE_CDMA_ACTIVATION_CODE = "bool_disable_cdma_activation_code"; + field public static final java.lang.String BOOL_DTMF_TYPE_ENABLED = "bool_dtmf_type_enabled"; + field public static final java.lang.String BOOL_ENABLE_DIALER_KEY_VIBRATION = "bool_enable_dialer_key_vibration"; + field public static final java.lang.String BOOL_HAS_IN_CALL_NOISE_SUPPRESSION = "bool_has_in_call_noise_suppression"; + field public static final java.lang.String BOOL_HIDE_CARRIER_NETWORK_SETTINGS = "bool_hide_carrier_network_settings"; + field public static final java.lang.String BOOL_IGNORE_SIM_NETWORK_LOCKED_EVENTS = "bool_ignore_sim_network_locked_events"; + field public static final java.lang.String BOOL_OPERATOR_SELECTION_EXPAND = "bool_operator_selection_expand"; + field public static final java.lang.String BOOL_PREFER_2G = "bool_prefer_2g"; field public static final java.lang.String BOOL_SHOW_APN_SETTING_CDMA = "bool_show_apn_setting_cdma"; + field public static final java.lang.String BOOL_SHOW_CDMA = "bool_show_cdma"; + field public static final java.lang.String BOOL_SHOW_ONSCREEN_DIAL_BUTTON = "bool_show_onscreen_dial_button"; + field public static final java.lang.String BOOL_SIM_NETWORK_UNLOCK_ALLOW_DISMISS = "bool_sim_network_unlock_allow_dismiss"; + field public static final java.lang.String BOOL_SUPPORT_PAUSE_IMS_VIDEO_CALLS = "bool_support_pause_ims_video_calls"; + field public static final java.lang.String BOOL_SUPPORT_SWAP_AFTER_MERGE = "bool_support_swap_after_merge"; + field public static final java.lang.String BOOL_USE_HFA_FOR_PROVISIONING = "bool_use_hfa_for_provisioning"; + field public static final java.lang.String BOOL_USE_OTASP_FOR_PROVISIONING = "bool_use_otasp_for_provisioning"; + field public static final java.lang.String BOOL_VOICEMAIL_NOTIFICATION_PERSISTENT = "bool_voicemail_notification_persistent"; + field public static final java.lang.String BOOL_VOICE_PRIVACY_DISABLE = "bool_voice_privacy_disable"; + field public static final java.lang.String BOOL_WORLD_PHONE = "bool_world_phone"; field public static final java.lang.String INT_VOLTE_REPLACEMENT_RAT = "int_volte_replacement_rat"; } @@ -33998,6 +34018,7 @@ package android.util { method public static void readEvents(int[], java.util.Collection<android.util.EventLog.Event>) throws java.io.IOException; method public static int writeEvent(int, int); method public static int writeEvent(int, long); + method public static int writeEvent(int, float); method public static int writeEvent(int, java.lang.String); method public static int writeEvent(int, java.lang.Object...); } diff --git a/api/system-current.txt b/api/system-current.txt index c9bdd065a7bc..0b887d595561 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -351,7 +351,7 @@ package android { field public static final int allowParallelSyncs = 16843570; // 0x1010332 field public static final int allowSingleTap = 16843353; // 0x1010259 field public static final int allowTaskReparenting = 16843268; // 0x1010204 - field public static final int allowUndo = 16844006; // 0x10104e6 + field public static final int allowUndo = 16844005; // 0x10104e5 field public static final int alpha = 16843551; // 0x101031f field public static final int alphabeticShortcut = 16843235; // 0x10101e3 field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef @@ -372,7 +372,7 @@ package android { field public static final int anyDensity = 16843372; // 0x101026c field public static final int apduServiceBanner = 16843757; // 0x10103ed field public static final int apiKey = 16843281; // 0x1010211 - field public static final int assistBlocked = 16844020; // 0x10104f4 + field public static final int assistBlocked = 16844019; // 0x10104f3 field public static final int author = 16843444; // 0x10102b4 field public static final int authorities = 16842776; // 0x1010018 field public static final int autoAdvanceViewId = 16843535; // 0x101030f @@ -383,7 +383,7 @@ package android { field public static final int autoStart = 16843445; // 0x10102b5 field public static final deprecated int autoText = 16843114; // 0x101016a field public static final int autoUrlDetect = 16843404; // 0x101028c - field public static final int autoVerify = 16844010; // 0x10104ea + field public static final int autoVerify = 16844009; // 0x10104e9 field public static final int background = 16842964; // 0x10100d4 field public static final int backgroundDimAmount = 16842802; // 0x1010032 field public static final int backgroundDimEnabled = 16843295; // 0x101021f @@ -407,7 +407,7 @@ package android { field public static final int bottomRightRadius = 16843180; // 0x10101ac field public static final int breadCrumbShortTitle = 16843524; // 0x1010304 field public static final int breadCrumbTitle = 16843523; // 0x1010303 - field public static final int breakStrategy = 16844011; // 0x10104eb + field public static final int breakStrategy = 16844010; // 0x10104ea field public static final int bufferType = 16843086; // 0x101014e field public static final int button = 16843015; // 0x1010107 field public static final int buttonBarButtonStyle = 16843567; // 0x101032f @@ -469,7 +469,7 @@ package android { field public static final int colorActivatedHighlight = 16843664; // 0x1010390 field public static final int colorBackground = 16842801; // 0x1010031 field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab - field public static final int colorBackgroundFloating = 16844007; // 0x10104e7 + field public static final int colorBackgroundFloating = 16844006; // 0x10104e6 field public static final int colorButtonNormal = 16843819; // 0x101042b field public static final int colorControlActivated = 16843818; // 0x101042a field public static final int colorControlHighlight = 16843820; // 0x101042c @@ -578,7 +578,7 @@ package android { field public static final int dropDownWidth = 16843362; // 0x1010262 field public static final int duplicateParentState = 16842985; // 0x10100e9 field public static final int duration = 16843160; // 0x1010198 - field public static final int dynamicResources = 16844019; // 0x10104f3 + field public static final int dynamicResources = 16844018; // 0x10104f2 field public static final int editTextBackground = 16843602; // 0x1010352 field public static final int editTextColor = 16843601; // 0x1010351 field public static final int editTextPreferenceStyle = 16842898; // 0x1010092 @@ -590,7 +590,7 @@ package android { field public static final int ellipsize = 16842923; // 0x10100ab field public static final int ems = 16843096; // 0x1010158 field public static final int enabled = 16842766; // 0x101000e - field public static final int end = 16843997; // 0x10104dd + field public static final int end = 16843996; // 0x10104dc field public static final int endColor = 16843166; // 0x101019e field public static final deprecated int endYear = 16843133; // 0x101017d field public static final int enterFadeDuration = 16843532; // 0x101030c @@ -612,7 +612,7 @@ package android { field public static final int expandableListViewWhiteStyle = 16843446; // 0x10102b6 field public static final int exported = 16842768; // 0x1010010 field public static final int extraTension = 16843371; // 0x101026b - field public static final int extractNativeLibs = 16844008; // 0x10104e8 + field public static final int extractNativeLibs = 16844007; // 0x10104e7 field public static final int factor = 16843219; // 0x10101d3 field public static final int fadeDuration = 16843384; // 0x1010278 field public static final int fadeEnabled = 16843390; // 0x101027e @@ -726,8 +726,8 @@ package android { field public static final int host = 16842792; // 0x1010028 field public static final int icon = 16842754; // 0x1010002 field public static final int iconPreview = 16843337; // 0x1010249 - field public static final int iconTint = 16844000; // 0x10104e0 - field public static final int iconTintMode = 16844001; // 0x10104e1 + field public static final int iconTint = 16843999; // 0x10104df + field public static final int iconTintMode = 16844000; // 0x10104e0 field public static final int iconifiedByDefault = 16843514; // 0x10102fa field public static final int id = 16842960; // 0x10100d0 field public static final int ignoreGravity = 16843263; // 0x10101ff @@ -867,7 +867,7 @@ package android { field public static final int layout_x = 16843135; // 0x101017f field public static final int layout_y = 16843136; // 0x1010180 field public static final int left = 16843181; // 0x10101ad - field public static final int leftIndents = 16844016; // 0x10104f0 + field public static final int leftIndents = 16844015; // 0x10104ef field public static final int letterSpacing = 16843958; // 0x10104b6 field public static final int lineSpacingExtra = 16843287; // 0x1010217 field public static final int lineSpacingMultiplier = 16843288; // 0x1010218 @@ -890,7 +890,7 @@ package android { field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208 field public static final int listViewStyle = 16842868; // 0x1010074 field public static final int listViewWhiteStyle = 16842869; // 0x1010075 - field public static final int lockTaskMode = 16844015; // 0x10104ef + field public static final int lockTaskMode = 16844014; // 0x10104ee field public static final int logo = 16843454; // 0x10102be field public static final int longClickable = 16842982; // 0x10100e6 field public static final int loopViews = 16843527; // 0x1010307 @@ -939,8 +939,8 @@ package android { field public static final int navigationContentDescription = 16843969; // 0x10104c1 field public static final int navigationIcon = 16843968; // 0x10104c0 field public static final int navigationMode = 16843471; // 0x10102cf - field public static final int navigationTint = 16844004; // 0x10104e4 - field public static final int navigationTintMode = 16844005; // 0x10104e5 + field public static final int navigationTint = 16844003; // 0x10104e3 + field public static final int navigationTintMode = 16844004; // 0x10104e4 field public static final int negativeButtonText = 16843254; // 0x10101f6 field public static final int nestedScrollingEnabled = 16843830; // 0x1010436 field public static final int nextFocusDown = 16842980; // 0x10100e4 @@ -954,7 +954,7 @@ package android { field public static final int numColumns = 16843032; // 0x1010118 field public static final int numStars = 16843076; // 0x1010144 field public static final int numbersBackgroundColor = 16843938; // 0x10104a2 - field public static final int numbersInnerTextColor = 16843999; // 0x10104df + field public static final int numbersInnerTextColor = 16843998; // 0x10104de field public static final int numbersSelectorColor = 16843939; // 0x10104a3 field public static final int numbersTextColor = 16843937; // 0x10104a1 field public static final deprecated int numeric = 16843109; // 0x1010165 @@ -972,8 +972,8 @@ package android { field public static final int overScrollFooter = 16843459; // 0x10102c3 field public static final int overScrollHeader = 16843458; // 0x10102c2 field public static final int overScrollMode = 16843457; // 0x10102c1 - field public static final int overflowTint = 16844002; // 0x10104e2 - field public static final int overflowTintMode = 16844003; // 0x10104e3 + field public static final int overflowTint = 16844001; // 0x10104e1 + field public static final int overflowTintMode = 16844002; // 0x10104e2 field public static final int overlapAnchor = 16843874; // 0x1010462 field public static final int overridesImplicitlyEnabledSubtype = 16843682; // 0x10103a2 field public static final int packageNames = 16843649; // 0x1010381 @@ -1068,7 +1068,7 @@ package android { field public static final int readPermission = 16842759; // 0x1010007 field public static final int recognitionService = 16843932; // 0x101049c field public static final int relinquishTaskIdentity = 16843894; // 0x1010476 - field public static final int removeBeforeMRelease = 16844014; // 0x10104ee + field public static final int removeBeforeMRelease = 16844013; // 0x10104ed field public static final int reparent = 16843964; // 0x10104bc field public static final int reparentWithOverlay = 16843965; // 0x10104bd field public static final int repeatCount = 16843199; // 0x10101bf @@ -1087,7 +1087,6 @@ package android { field public static final int resizeClip = 16843983; // 0x10104cf field public static final int resizeMode = 16843619; // 0x1010363 field public static final int resizeable = 16843405; // 0x101028d - field public static final int resizeableActivity = 16843995; // 0x10104db field public static final int resource = 16842789; // 0x1010025 field public static final int restoreAnyVersion = 16843450; // 0x10102ba field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d @@ -1097,7 +1096,7 @@ package android { field public static final int reversible = 16843851; // 0x101044b field public static final int revisionCode = 16843989; // 0x10104d5 field public static final int right = 16843183; // 0x10101af - field public static final int rightIndents = 16844017; // 0x10104f1 + field public static final int rightIndents = 16844016; // 0x10104f0 field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093 field public static final int ringtoneType = 16843257; // 0x10101f9 field public static final int rotation = 16843558; // 0x1010326 @@ -1177,7 +1176,7 @@ package android { field public static final int showAsAction = 16843481; // 0x10102d9 field public static final int showDefault = 16843258; // 0x10101fa field public static final int showDividers = 16843561; // 0x1010329 - field public static final int showForAllUsers = 16844018; // 0x10104f2 + field public static final int showForAllUsers = 16844017; // 0x10104f1 field public static final deprecated int showOnLockScreen = 16843721; // 0x10103c9 field public static final int showSilent = 16843259; // 0x10101fb field public static final int showText = 16843949; // 0x10104ad @@ -1207,7 +1206,7 @@ package android { field public static final int stackFromBottom = 16843005; // 0x10100fd field public static final int stackViewStyle = 16843838; // 0x101043e field public static final int starStyle = 16842882; // 0x1010082 - field public static final int start = 16843996; // 0x10104dc + field public static final int start = 16843995; // 0x10104db field public static final int startColor = 16843165; // 0x101019d field public static final int startDelay = 16843746; // 0x10103e2 field public static final int startOffset = 16843198; // 0x10101be @@ -1263,7 +1262,7 @@ package android { field public static final int summaryColumn = 16843426; // 0x10102a2 field public static final int summaryOff = 16843248; // 0x10101f0 field public static final int summaryOn = 16843247; // 0x10101ef - field public static final int supportsAssistGesture = 16844012; // 0x10104ec + field public static final int supportsAssistGesture = 16844011; // 0x10104eb field public static final int supportsRtl = 16843695; // 0x10103af field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb field public static final int supportsUploading = 16843419; // 0x101029b @@ -1364,7 +1363,7 @@ package android { field public static final int thicknessRatio = 16843164; // 0x101019c field public static final int thumb = 16843074; // 0x1010142 field public static final int thumbOffset = 16843075; // 0x1010143 - field public static final int thumbPosition = 16844013; // 0x10104ed + field public static final int thumbPosition = 16844012; // 0x10104ec field public static final int thumbTextPadding = 16843634; // 0x1010372 field public static final int thumbTint = 16843889; // 0x1010471 field public static final int thumbTintMode = 16843890; // 0x1010472 @@ -1428,7 +1427,7 @@ package android { field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310 field public static final int useLevel = 16843167; // 0x101019f field public static final int userVisible = 16843409; // 0x1010291 - field public static final int usesCleartextTraffic = 16844009; // 0x10104e9 + field public static final int usesCleartextTraffic = 16844008; // 0x10104e8 field public static final int value = 16842788; // 0x1010024 field public static final int valueFrom = 16843486; // 0x10102de field public static final int valueTo = 16843487; // 0x10102df @@ -1493,10 +1492,10 @@ package android { field public static final int windowExitTransition = 16843832; // 0x1010438 field public static final int windowFrame = 16842837; // 0x1010055 field public static final int windowFullscreen = 16843277; // 0x101020d - field public static final int windowLightStatusBar = 16843998; // 0x10104de field public static final int windowHideAnimation = 16842935; // 0x10100b7 field public static final int windowIsFloating = 16842839; // 0x1010057 field public static final int windowIsTranslucent = 16842840; // 0x1010058 + field public static final int windowLightStatusBar = 16843997; // 0x10104dd field public static final int windowMinWidthMajor = 16843606; // 0x1010356 field public static final int windowMinWidthMinor = 16843607; // 0x1010357 field public static final int windowNoDisplay = 16843294; // 0x101021e @@ -3950,6 +3949,7 @@ package android.app { method public void finishOp(java.lang.String, int, java.lang.String); method public int noteOp(java.lang.String, int, java.lang.String); method public int noteOpNoThrow(java.lang.String, int, java.lang.String); + method public static java.lang.String permissionToOp(java.lang.String); method public int startOp(java.lang.String, int, java.lang.String); method public int startOpNoThrow(java.lang.String, int, java.lang.String); method public void startWatchingMode(java.lang.String, java.lang.String, android.app.AppOpsManager.OnOpChangedListener); @@ -5828,6 +5828,7 @@ package android.app.admin { method public int getPasswordMinimumSymbols(android.content.ComponentName); method public int getPasswordMinimumUpperCase(android.content.ComponentName); method public int getPasswordQuality(android.content.ComponentName); + method public int getPermissionPolicy(android.content.ComponentName); method public java.util.List<java.lang.String> getPermittedAccessibilityServices(android.content.ComponentName); method public java.util.List<java.lang.String> getPermittedAccessibilityServices(int); method public java.util.List<java.lang.String> getPermittedInputMethods(android.content.ComponentName); @@ -5886,6 +5887,8 @@ package android.app.admin { method public void setPasswordMinimumSymbols(android.content.ComponentName, int); method public void setPasswordMinimumUpperCase(android.content.ComponentName, int); method public void setPasswordQuality(android.content.ComponentName, int); + method public boolean setPermissionGranted(android.content.ComponentName, java.lang.String, java.lang.String, boolean); + method public void setPermissionPolicy(android.content.ComponentName, int); method public boolean setPermittedAccessibilityServices(android.content.ComponentName, java.util.List<java.lang.String>); method public boolean setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>); method public void setPreferredSetupActivity(android.content.ComponentName, android.content.ComponentName); @@ -5979,6 +5982,9 @@ package android.app.admin { field public static final int PASSWORD_QUALITY_NUMERIC_COMPLEX = 196608; // 0x30000 field public static final int PASSWORD_QUALITY_SOMETHING = 65536; // 0x10000 field public static final int PASSWORD_QUALITY_UNSPECIFIED = 0; // 0x0 + field public static final int PERMISSION_POLICY_AUTO_DENY = 2; // 0x2 + field public static final int PERMISSION_POLICY_AUTO_GRANT = 1; // 0x1 + field public static final int PERMISSION_POLICY_PROMPT = 0; // 0x0 field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1 field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1 field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 @@ -9697,6 +9703,7 @@ package android.content.pm { field public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103; // 0xffffff99 field public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102; // 0xffffff9a field public static final int INSTALL_SUCCEEDED = 1; // 0x1 + field public static final int MATCH_ALL = 131072; // 0x20000 field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000 field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L field public static final int PERMISSION_DENIED = -1; // 0xffffffff @@ -14923,6 +14930,7 @@ package android.hardware.usb { method public java.lang.String getProductName(); method public java.lang.String getSerialNumber(); method public int getVendorId(); + method public java.lang.String getVersion(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.hardware.usb.UsbDevice> CREATOR; } @@ -15465,6 +15473,7 @@ package android.location { method public boolean hasPseudorangeUncertaintyInMeters(); method public boolean hasSnrInDb(); method public boolean hasTimeFromLastBitInMs(); + method public boolean isPseudorangeRateCorrected(); method public boolean isUsedInFix(); method public void reset(); method public void resetAzimuthInDeg(); @@ -15530,6 +15539,7 @@ package android.location { field public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0 field public static final short STATE_BIT_SYNC = 2; // 0x2 field public static final short STATE_CODE_LOCK = 1; // 0x1 + field public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10 field public static final short STATE_SUBFRAME_SYNC = 4; // 0x4 field public static final short STATE_TOW_DECODED = 8; // 0x8 field public static final short STATE_UNKNOWN = 0; // 0x0 @@ -15557,6 +15567,7 @@ package android.location { method public byte[] getData(); method public short getMessageId(); method public byte getPrn(); + method public short getStatus(); method public short getSubmessageId(); method public byte getType(); method public void reset(); @@ -15564,10 +15575,14 @@ package android.location { method public void setData(byte[]); method public void setMessageId(short); method public void setPrn(byte); + method public void setStatus(short); method public void setSubmessageId(short); method public void setType(byte); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessage> CREATOR; + field public static final short STATUS_PARITY_PASSED = 1; // 0x1 + field public static final short STATUS_PARITY_REBUILT = 2; // 0x2 + field public static final short STATUS_UNKNOWN = 0; // 0x0 field public static final byte TYPE_CNAV2 = 4; // 0x4 field public static final byte TYPE_L1CA = 1; // 0x1 field public static final byte TYPE_L2CNAV = 2; // 0x2 @@ -18545,6 +18560,7 @@ package android.media.midi { field public static final java.lang.String PROPERTY_PRODUCT = "product"; field public static final java.lang.String PROPERTY_SERIAL_NUMBER = "serial_number"; field public static final java.lang.String PROPERTY_USB_DEVICE = "usb_device"; + field public static final java.lang.String PROPERTY_VERSION = "version"; field public static final int TYPE_BLUETOOTH = 3; // 0x3 field public static final int TYPE_USB = 1; // 0x1 field public static final int TYPE_VIRTUAL = 2; // 0x2 @@ -30534,10 +30550,9 @@ package android.security { method public java.lang.String getKeystoreAlias(); method public int getPurposes(); method public int getUserAuthenticationValidityDurationSeconds(); - method public int getUserAuthenticators(); method public boolean isEncryptionRequired(); - method public boolean isInvalidatedOnNewFingerprintEnrolled(); method public boolean isRandomizedEncryptionRequired(); + method public boolean isUserAuthenticationRequired(); } public static class KeyGeneratorSpec.Builder { @@ -30547,7 +30562,6 @@ package android.security { method public android.security.KeyGeneratorSpec.Builder setBlockModes(java.lang.String...); method public android.security.KeyGeneratorSpec.Builder setEncryptionPaddings(java.lang.String...); method public android.security.KeyGeneratorSpec.Builder setEncryptionRequired(boolean); - method public android.security.KeyGeneratorSpec.Builder setInvalidatedOnNewFingerprintEnrolled(boolean); method public android.security.KeyGeneratorSpec.Builder setKeySize(int); method public android.security.KeyGeneratorSpec.Builder setKeyValidityEnd(java.util.Date); method public android.security.KeyGeneratorSpec.Builder setKeyValidityForConsumptionEnd(java.util.Date); @@ -30555,8 +30569,8 @@ package android.security { method public android.security.KeyGeneratorSpec.Builder setKeyValidityStart(java.util.Date); method public android.security.KeyGeneratorSpec.Builder setPurposes(int); method public android.security.KeyGeneratorSpec.Builder setRandomizedEncryptionRequired(boolean); + method public android.security.KeyGeneratorSpec.Builder setUserAuthenticationRequired(boolean); method public android.security.KeyGeneratorSpec.Builder setUserAuthenticationValidityDurationSeconds(int); - method public android.security.KeyGeneratorSpec.Builder setUserAuthenticators(int); } public class KeyNotYetValidException extends java.security.InvalidKeyException { @@ -30584,10 +30598,9 @@ package android.security { method public java.util.Date getStartDate(); method public javax.security.auth.x500.X500Principal getSubjectDN(); method public int getUserAuthenticationValidityDurationSeconds(); - method public int getUserAuthenticators(); method public boolean isEncryptionRequired(); - method public boolean isInvalidatedOnNewFingerprintEnrolled(); method public boolean isRandomizedEncryptionRequired(); + method public boolean isUserAuthenticationRequired(); } public static final class KeyPairGeneratorSpec.Builder { @@ -30600,7 +30613,6 @@ package android.security { method public android.security.KeyPairGeneratorSpec.Builder setEncryptionPaddings(java.lang.String...); method public android.security.KeyPairGeneratorSpec.Builder setEncryptionRequired(); method public android.security.KeyPairGeneratorSpec.Builder setEndDate(java.util.Date); - method public android.security.KeyPairGeneratorSpec.Builder setInvalidatedOnNewFingerprintEnrolled(boolean); method public android.security.KeyPairGeneratorSpec.Builder setKeySize(int); method public android.security.KeyPairGeneratorSpec.Builder setKeyType(java.lang.String) throws java.security.NoSuchAlgorithmException; method public android.security.KeyPairGeneratorSpec.Builder setKeyValidityEnd(java.util.Date); @@ -30613,8 +30625,8 @@ package android.security { method public android.security.KeyPairGeneratorSpec.Builder setSignaturePaddings(java.lang.String...); method public android.security.KeyPairGeneratorSpec.Builder setStartDate(java.util.Date); method public android.security.KeyPairGeneratorSpec.Builder setSubject(javax.security.auth.x500.X500Principal); + method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticationRequired(boolean); method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticationValidityDurationSeconds(int); - method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticators(int); } public abstract class KeyStoreKeyProperties { @@ -30639,14 +30651,6 @@ package android.security { public static abstract class KeyStoreKeyProperties.PurposeEnum implements java.lang.annotation.Annotation { } - public static abstract class KeyStoreKeyProperties.UserAuthenticator { - field public static final int FINGERPRINT_READER = 2; // 0x2 - field public static final int LOCK_SCREEN = 1; // 0x1 - } - - public static abstract class KeyStoreKeyProperties.UserAuthenticatorEnum implements java.lang.annotation.Annotation { - } - public class KeyStoreKeySpec implements java.security.spec.KeySpec { method public java.lang.String[] getBlockModes(); method public java.lang.String[] getDigests(); @@ -30659,15 +30663,15 @@ package android.security { method public int getOrigin(); method public int getPurposes(); method public java.lang.String[] getSignaturePaddings(); - method public int getTeeEnforcedUserAuthenticators(); method public int getUserAuthenticationValidityDurationSeconds(); - method public int getUserAuthenticators(); - method public boolean isInvalidatedOnNewFingerprintEnrolled(); method public boolean isTeeBacked(); + method public boolean isUserAuthenticationRequired(); + method public boolean isUserAuthenticationRequirementTeeEnforced(); } public final class KeyStoreParameter implements java.security.KeyStore.ProtectionParameter { method public java.lang.String[] getBlockModes(); + method public android.content.Context getContext(); method public java.lang.String[] getDigests(); method public java.lang.String[] getEncryptionPaddings(); method public java.util.Date getKeyValidityForConsumptionEnd(); @@ -30676,11 +30680,10 @@ package android.security { method public int getPurposes(); method public java.lang.String[] getSignaturePaddings(); method public int getUserAuthenticationValidityDurationSeconds(); - method public int getUserAuthenticators(); method public boolean isDigestsSpecified(); method public boolean isEncryptionRequired(); - method public boolean isInvalidatedOnNewFingerprintEnrolled(); method public boolean isRandomizedEncryptionRequired(); + method public boolean isUserAuthenticationRequired(); } public static final class KeyStoreParameter.Builder { @@ -30690,7 +30693,6 @@ package android.security { method public android.security.KeyStoreParameter.Builder setDigests(java.lang.String...); method public android.security.KeyStoreParameter.Builder setEncryptionPaddings(java.lang.String...); method public android.security.KeyStoreParameter.Builder setEncryptionRequired(boolean); - method public android.security.KeyStoreParameter.Builder setInvalidatedOnNewFingerprintEnrolled(boolean); method public android.security.KeyStoreParameter.Builder setKeyValidityEnd(java.util.Date); method public android.security.KeyStoreParameter.Builder setKeyValidityForConsumptionEnd(java.util.Date); method public android.security.KeyStoreParameter.Builder setKeyValidityForOriginationEnd(java.util.Date); @@ -30698,8 +30700,8 @@ package android.security { method public android.security.KeyStoreParameter.Builder setPurposes(int); method public android.security.KeyStoreParameter.Builder setRandomizedEncryptionRequired(boolean); method public android.security.KeyStoreParameter.Builder setSignaturePaddings(java.lang.String...); + method public android.security.KeyStoreParameter.Builder setUserAuthenticationRequired(boolean); method public android.security.KeyStoreParameter.Builder setUserAuthenticationValidityDurationSeconds(int); - method public android.security.KeyStoreParameter.Builder setUserAuthenticators(int); } public class NetworkSecurityPolicy { @@ -31314,6 +31316,7 @@ package android.speech { field public static final java.lang.String EXTRA_ONLY_RETURN_LANGUAGE_PREFERENCE = "android.speech.extra.ONLY_RETURN_LANGUAGE_PREFERENCE"; field public static final java.lang.String EXTRA_ORIGIN = "android.speech.extra.ORIGIN"; field public static final java.lang.String EXTRA_PARTIAL_RESULTS = "android.speech.extra.PARTIAL_RESULTS"; + field public static final java.lang.String EXTRA_PREFER_OFFLINE = "android.speech.extra.PREFER_OFFLINE"; field public static final java.lang.String EXTRA_PROMPT = "android.speech.extra.PROMPT"; field public static final java.lang.String EXTRA_RESULTS = "android.speech.extra.RESULTS"; field public static final java.lang.String EXTRA_RESULTS_PENDINGINTENT = "android.speech.extra.RESULTS_PENDINGINTENT"; @@ -32550,7 +32553,6 @@ package android.telecom { public static abstract class InCallService.VideoCall { ctor public InCallService.VideoCall(); method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback); - method public abstract void unregisterCallback(); method public abstract void requestCallDataUsage(); method public abstract void requestCameraCapabilities(); method public abstract void sendSessionModifyRequest(android.telecom.VideoProfile); @@ -32561,6 +32563,7 @@ package android.telecom { method public abstract void setPauseImage(java.lang.String); method public abstract void setPreviewSurface(android.view.Surface); method public abstract void setZoom(float); + method public abstract void unregisterCallback(); } public static abstract class InCallService.VideoCall.Callback { @@ -32846,11 +32849,34 @@ package android.telephony { method public void reloadCarrierConfigForSubId(int); method public void updateConfigForPhoneId(int, java.lang.String); field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED"; + field public static final java.lang.String BOOL_ADDITIONAL_CALL_SETTING = "bool_additional_call_setting"; + field public static final java.lang.String BOOL_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG = "bool_allow_emergency_numbers_in_call_log"; + field public static final java.lang.String BOOL_ALLOW_LOCAL_DTMF_TONES = "bool_allow_local_dtmf_tones"; field public static final java.lang.String BOOL_APN_EXPAND = "bool_apn_expand"; + field public static final java.lang.String BOOL_AUTO_RETRY_ENABLED = "bool_auto_retry_enabled"; + field public static final java.lang.String BOOL_CARRIER_SETTINGS_ENABLE = "bool_carrier_settings_enable"; field public static final java.lang.String BOOL_CARRIER_VOLTE_AVAILABLE = "bool_carrier_volte_available"; field public static final java.lang.String BOOL_CARRIER_VOLTE_PROVISIONED = "bool_carrier_volte_provisioned"; field public static final java.lang.String BOOL_CARRIER_VOLTE_TTY_SUPPORTED = "bool_carrier_volte_tty_supported"; + field public static final java.lang.String BOOL_DISABLE_CDMA_ACTIVATION_CODE = "bool_disable_cdma_activation_code"; + field public static final java.lang.String BOOL_DTMF_TYPE_ENABLED = "bool_dtmf_type_enabled"; + field public static final java.lang.String BOOL_ENABLE_DIALER_KEY_VIBRATION = "bool_enable_dialer_key_vibration"; + field public static final java.lang.String BOOL_HAS_IN_CALL_NOISE_SUPPRESSION = "bool_has_in_call_noise_suppression"; + field public static final java.lang.String BOOL_HIDE_CARRIER_NETWORK_SETTINGS = "bool_hide_carrier_network_settings"; + field public static final java.lang.String BOOL_IGNORE_SIM_NETWORK_LOCKED_EVENTS = "bool_ignore_sim_network_locked_events"; + field public static final java.lang.String BOOL_OPERATOR_SELECTION_EXPAND = "bool_operator_selection_expand"; + field public static final java.lang.String BOOL_PREFER_2G = "bool_prefer_2g"; field public static final java.lang.String BOOL_SHOW_APN_SETTING_CDMA = "bool_show_apn_setting_cdma"; + field public static final java.lang.String BOOL_SHOW_CDMA = "bool_show_cdma"; + field public static final java.lang.String BOOL_SHOW_ONSCREEN_DIAL_BUTTON = "bool_show_onscreen_dial_button"; + field public static final java.lang.String BOOL_SIM_NETWORK_UNLOCK_ALLOW_DISMISS = "bool_sim_network_unlock_allow_dismiss"; + field public static final java.lang.String BOOL_SUPPORT_PAUSE_IMS_VIDEO_CALLS = "bool_support_pause_ims_video_calls"; + field public static final java.lang.String BOOL_SUPPORT_SWAP_AFTER_MERGE = "bool_support_swap_after_merge"; + field public static final java.lang.String BOOL_USE_HFA_FOR_PROVISIONING = "bool_use_hfa_for_provisioning"; + field public static final java.lang.String BOOL_USE_OTASP_FOR_PROVISIONING = "bool_use_otasp_for_provisioning"; + field public static final java.lang.String BOOL_VOICEMAIL_NOTIFICATION_PERSISTENT = "bool_voicemail_notification_persistent"; + field public static final java.lang.String BOOL_VOICE_PRIVACY_DISABLE = "bool_voice_privacy_disable"; + field public static final java.lang.String BOOL_WORLD_PHONE = "bool_world_phone"; field public static final java.lang.String INT_VOLTE_REPLACEMENT_RAT = "int_volte_replacement_rat"; } @@ -36202,6 +36228,7 @@ package android.util { method public static void readEvents(int[], java.util.Collection<android.util.EventLog.Event>) throws java.io.IOException; method public static int writeEvent(int, int); method public static int writeEvent(int, long); + method public static int writeEvent(int, float); method public static int writeEvent(int, java.lang.String); method public static int writeEvent(int, java.lang.Object...); } diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 223d528a6c1d..48e380b42b75 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -726,6 +726,16 @@ public class AppOpsManager { false }; + /** + * This is a mapping from a permission name to public app op name. + */ + private static final ArrayMap<String, String> sPermToOp = new ArrayMap<>(); + static { + sPermToOp.put(Manifest.permission.ACCESS_COARSE_LOCATION, OPSTR_COARSE_LOCATION); + sPermToOp.put(Manifest.permission.ACCESS_FINE_LOCATION, OPSTR_FINE_LOCATION); + sPermToOp.put(Manifest.permission.PACKAGE_USAGE_STATS, OPSTR_GET_USAGE_STATS); + } + private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>(); static { @@ -1066,6 +1076,21 @@ public class AppOpsManager { } /** + * Gets the app op name associated with a given permission. + * The app op name is one of the public constants defined + * in this class such as {@link #OPSTR_COARSE_LOCATION}. + * + * @param permission The permission. + * @return The app op associated with the permission or null. + * + * @hide + */ + @SystemApi + public static String permissionToOp(String permission) { + return sPermToOp.get(permission); + } + + /** * Monitor for changes to the operating mode for the given op in the given app package. * @param op The operation to monitor, one of OPSTR_*. * @param packageName The name of the application to monitor. diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 16a2430a93d7..6e511f38f7e7 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -79,6 +79,7 @@ import android.view.Display; import dalvik.system.VMRuntime; import com.android.internal.annotations.GuardedBy; +import com.android.internal.os.SomeArgs; import com.android.internal.util.Preconditions; import com.android.internal.util.UserIcons; @@ -2054,8 +2055,7 @@ final class ApplicationPackageManager extends PackageManager { /** {@hide} */ private static class MoveCallbackDelegate extends IPackageMoveObserver.Stub implements Handler.Callback { - private static final int MSG_STARTED = 1; - private static final int MSG_STATUS_CHANGED = 2; + private static final int MSG_STATUS_CHANGED = 1; final MoveCallback mCallback; final Handler mHandler; @@ -2067,26 +2067,25 @@ final class ApplicationPackageManager extends PackageManager { @Override public boolean handleMessage(Message msg) { - final int moveId = msg.arg1; switch (msg.what) { - case MSG_STARTED: - mCallback.onStarted(moveId, (String) msg.obj); - return true; case MSG_STATUS_CHANGED: - mCallback.onStatusChanged(moveId, msg.arg2, (long) msg.obj); + final SomeArgs args = (SomeArgs) msg.obj; + mCallback.onStatusChanged(args.argi1, (String) args.arg2, args.argi3, + (long) args.arg4); + args.recycle(); return true; } return false; } @Override - public void onStarted(int moveId, String title) { - mHandler.obtainMessage(MSG_STARTED, moveId, 0, title).sendToTarget(); - } - - @Override - public void onStatusChanged(int moveId, int status, long estMillis) { - mHandler.obtainMessage(MSG_STATUS_CHANGED, moveId, status, estMillis).sendToTarget(); + public void onStatusChanged(int moveId, String moveTitle, int status, long estMillis) { + final SomeArgs args = SomeArgs.obtain(); + args.argi1 = moveId; + args.arg2 = moveTitle; + args.argi3 = status; + args.arg4 = estMillis; + mHandler.obtainMessage(MSG_STATUS_CHANGED, args).sendToTarget(); } } diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index 207519c4325d..31d1ab7b92ac 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -63,12 +63,20 @@ public class StatusBarManager { | DISABLE_SYSTEM_INFO | DISABLE_RECENT | DISABLE_HOME | DISABLE_BACK | DISABLE_CLOCK | DISABLE_SEARCH; + /** + * Flag to disable quick settings. + * + * Setting this flag disables quick settings completely, but does not disable expanding the + * notification shade. + */ + public static final int DISABLE2_QUICK_SETTINGS = 0x00000001; + public static final int DISABLE2_NONE = 0x00000000; - public static final int DISABLE2_MASK = 0x00000000; + public static final int DISABLE2_MASK = DISABLE2_QUICK_SETTINGS; @IntDef(flag = true, - value = {DISABLE2_NONE, DISABLE2_MASK}) + value = {DISABLE2_NONE, DISABLE2_MASK, DISABLE2_QUICK_SETTINGS}) @Retention(RetentionPolicy.SOURCE) public @interface Disable2Flags {} diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index ed814c3b4d27..cf9813fcaf8d 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -807,6 +807,24 @@ public class DevicePolicyManager { public static final String ACTION_SYSTEM_UPDATE_POLICY_CHANGED = "android.app.action.SYSTEM_UPDATE_POLICY_CHANGED"; + /** + * Permission policy to prompt user for new permission requests for runtime permissions. + * Already granted or denied permissions are not affected by this. + */ + public static final int PERMISSION_POLICY_PROMPT = 0; + + /** + * Permission policy to always grant new permission requests for runtime permissions. + * Already granted or denied permissions are not affected by this. + */ + public static final int PERMISSION_POLICY_AUTO_GRANT = 1; + + /** + * Permission policy to always deny new permission requests for runtime permissions. + * Already granted or denied permissions are not affected by this. + */ + public static final int PERMISSION_POLICY_AUTO_DENY = 2; + /** * Return true if the given administrator component is currently @@ -4342,4 +4360,58 @@ public class DevicePolicyManager { Log.w(TAG, "Failed talking with device policy service", re); } } + + /** + * Called by profile or device owners to set the default response for future runtime permission + * requests by applications. The policy can allow for normal operation which prompts the + * user to grant a permission, or can allow automatic granting or denying of runtime + * permission requests by an application. This also applies to new permissions declared by app + * updates. + * @param admin Which profile or device owner this request is associated with. + * @param policy One of the policy constants {@link #PERMISSION_POLICY_PROMPT}, + * {@link #PERMISSION_POLICY_AUTO_GRANT} and {@link #PERMISSION_POLICY_AUTO_DENY}. + */ + public void setPermissionPolicy(ComponentName admin, int policy) { + try { + mService.setPermissionPolicy(admin, policy); + } catch (RemoteException re) { + Log.w(TAG, "Failed talking with device policy service", re); + } + } + + /** + * Returns the current runtime permission policy set by the device or profile owner. The + * default is {@link #PERMISSION_POLICY_PROMPT}. + * @param admin Which profile or device owner this request is associated with. + * @return the current policy for future permission requests. + */ + public int getPermissionPolicy(ComponentName admin) { + try { + return mService.getPermissionPolicy(admin); + } catch (RemoteException re) { + return PERMISSION_POLICY_PROMPT; + } + } + + /** + * Grants or revokes a runtime permission to a specific application so that the user + * does not have to be prompted. This might affect all permissions in a group that the + * runtime permission belongs to. This method can only be called by a profile or device + * owner. + * @param admin Which profile or device owner this request is associated with. + * @param packageName The application to grant or revoke a permission to. + * @param permission The permission to grant or revoke. + * @param granted Whether or not to grant the permission. If false, all permissions in the + * associated permission group will be denied. + * @return whether the permission was successfully granted or revoked + */ + public boolean setPermissionGranted(ComponentName admin, String packageName, + String permission, boolean granted) { + try { + return mService.setPermissionGranted(admin, packageName, permission, granted); + } catch (RemoteException re) { + Log.w(TAG, "Failed talking with device policy service", re); + return false; + } + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index a678c51de482..833bc0063e51 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -229,4 +229,9 @@ interface IDevicePolicyManager { boolean getDoNotAskCredentialsOnBoot(); void notifyPendingSystemUpdate(in long updateReceivedTime); + + void setPermissionPolicy(in ComponentName admin, int policy); + int getPermissionPolicy(in ComponentName admin); + boolean setPermissionGranted(in ComponentName admin, String packageName, String permission, + boolean granted); } diff --git a/core/java/android/content/pm/IPackageMoveObserver.aidl b/core/java/android/content/pm/IPackageMoveObserver.aidl index 50ab3b5c6a5f..155ed0bf57d8 100644 --- a/core/java/android/content/pm/IPackageMoveObserver.aidl +++ b/core/java/android/content/pm/IPackageMoveObserver.aidl @@ -22,6 +22,5 @@ package android.content.pm; * @hide */ oneway interface IPackageMoveObserver { - void onStarted(int moveId, String title); - void onStatusChanged(int moveId, int status, long estMillis); + void onStatusChanged(int moveId, String moveTitle, int status, long estMillis); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e1c271dbe13d..a1ee7fcf83a9 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -209,7 +209,14 @@ public abstract class PackageManager { * matching. This is a synonym for including the CATEGORY_DEFAULT in your * supplied Intent. */ - public static final int MATCH_DEFAULT_ONLY = 0x00010000; + public static final int MATCH_DEFAULT_ONLY = 0x00010000; + + /** + * Querying flag: if set and if the platform is doing any filtering of the results, then + * the filtering will not happen. This is a synonym for saying that all results should + * be returned. + */ + public static final int MATCH_ALL = 0x00020000; /** * Flag for {@link addCrossProfileIntentFilter}: if this flag is set: @@ -2637,6 +2644,8 @@ public abstract class PackageManager { * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}. * + * You can also set {@link #MATCH_ALL} for preventing the filtering of the results. + * * @return A List<ResolveInfo> containing one entry for each matching * Activity. These are ordered from best to worst match -- that * is, the first item in the list is what is returned by @@ -2658,6 +2667,8 @@ public abstract class PackageManager { * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}. * + * You can also set {@link #MATCH_ALL} for preventing the filtering of the results. + * * @return A List<ResolveInfo> containing one entry for each matching * Activity. These are ordered from best to worst match -- that * is, the first item in the list is what is returned by @@ -4201,8 +4212,8 @@ public abstract class PackageManager { /** {@hide} */ public static abstract class MoveCallback { - public abstract void onStarted(int moveId, String title); - public abstract void onStatusChanged(int moveId, int status, long estMillis); + public abstract void onStatusChanged(int moveId, String moveTitle, int status, + long estMillis); } /** {@hide} */ diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index adab9be1d698..02793f1971fd 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -182,6 +182,10 @@ public abstract class DisplayManagerInternal { // The screen auto-brightness adjustment factor in the range -1 (dimmer) to 1 (brighter). public float screenAutoBrightnessAdjustment; + // Set to true if screenBrightness and screenAutoBrightnessAdjustment were both + // set by the user as opposed to being programmatically controlled by apps. + public boolean brightnessSetByUser; + // If true, enables automatic brightness control. public boolean useAutoBrightness; @@ -229,6 +233,7 @@ public abstract class DisplayManagerInternal { useProximitySensor = other.useProximitySensor; screenBrightness = other.screenBrightness; screenAutoBrightnessAdjustment = other.screenAutoBrightnessAdjustment; + brightnessSetByUser = other.brightnessSetByUser; useAutoBrightness = other.useAutoBrightness; blockScreenOn = other.blockScreenOn; lowPowerMode = other.lowPowerMode; @@ -249,6 +254,7 @@ public abstract class DisplayManagerInternal { && useProximitySensor == other.useProximitySensor && screenBrightness == other.screenBrightness && screenAutoBrightnessAdjustment == other.screenAutoBrightnessAdjustment + && brightnessSetByUser == other.brightnessSetByUser && useAutoBrightness == other.useAutoBrightness && blockScreenOn == other.blockScreenOn && lowPowerMode == other.lowPowerMode @@ -268,6 +274,7 @@ public abstract class DisplayManagerInternal { + ", useProximitySensor=" + useProximitySensor + ", screenBrightness=" + screenBrightness + ", screenAutoBrightnessAdjustment=" + screenAutoBrightnessAdjustment + + ", brightnessSetByUser=" + brightnessSetByUser + ", useAutoBrightness=" + useAutoBrightness + ", blockScreenOn=" + blockScreenOn + ", lowPowerMode=" + lowPowerMode diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java index 1a42319f475d..410d55010363 100644 --- a/core/java/android/hardware/usb/UsbDevice.java +++ b/core/java/android/hardware/usb/UsbDevice.java @@ -45,6 +45,7 @@ public class UsbDevice implements Parcelable { private final String mName; private final String mManufacturerName; private final String mProductName; + private final String mVersion; private final String mSerialNumber; private final int mVendorId; private final int mProductId; @@ -62,7 +63,7 @@ public class UsbDevice implements Parcelable { */ public UsbDevice(String name, int vendorId, int productId, int Class, int subClass, int protocol, - String manufacturerName, String productName, String serialNumber) { + String manufacturerName, String productName, String version, String serialNumber) { mName = name; mVendorId = vendorId; mProductId = productId; @@ -71,6 +72,7 @@ public class UsbDevice implements Parcelable { mProtocol = protocol; mManufacturerName = manufacturerName; mProductName = productName; + mVersion = version; mSerialNumber = serialNumber; } @@ -104,6 +106,15 @@ public class UsbDevice implements Parcelable { } /** + * Returns the version number of the device. + * + * @return the device version + */ + public String getVersion() { + return mVersion; + } + + /** * Returns the serial number of the device. * * @return the serial number name @@ -263,7 +274,7 @@ public class UsbDevice implements Parcelable { ",mVendorId=" + mVendorId + ",mProductId=" + mProductId + ",mClass=" + mClass + ",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol + ",mManufacturerName=" + mManufacturerName + ",mProductName=" + mProductName + - ",mSerialNumber=" + mSerialNumber + ",mConfigurations=["); + ",mVersion=" + mVersion + ",mSerialNumber=" + mSerialNumber + ",mConfigurations=["); for (int i = 0; i < mConfigurations.length; i++) { builder.append("\n"); builder.append(mConfigurations[i].toString()); @@ -283,10 +294,11 @@ public class UsbDevice implements Parcelable { int protocol = in.readInt(); String manufacturerName = in.readString(); String productName = in.readString(); + String version = in.readString(); String serialNumber = in.readString(); Parcelable[] configurations = in.readParcelableArray(UsbInterface.class.getClassLoader()); UsbDevice device = new UsbDevice(name, vendorId, productId, clasz, subClass, protocol, - manufacturerName, productName, serialNumber); + manufacturerName, productName, version, serialNumber); device.setConfigurations(configurations); return device; } @@ -309,6 +321,7 @@ public class UsbDevice implements Parcelable { parcel.writeInt(mProtocol); parcel.writeString(mManufacturerName); parcel.writeString(mProductName); + parcel.writeString(mVersion); parcel.writeString(mSerialNumber); parcel.writeParcelableArray(mConfigurations, 0); } diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl index c722fbce32bf..7f5f3776d355 100644 --- a/core/java/android/net/INetworkPolicyManager.aidl +++ b/core/java/android/net/INetworkPolicyManager.aidl @@ -38,8 +38,6 @@ interface INetworkPolicyManager { boolean isUidForeground(int uid); - int[] getPowerSaveAppIdWhitelist(); - void registerListener(INetworkPolicyListener listener); void unregisterListener(INetworkPolicyListener listener); diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index bc036376735d..b4c7b2b4d4d2 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -129,14 +129,6 @@ public class NetworkPolicyManager { } } - public int[] getPowerSaveAppIdWhitelist() { - try { - return mService.getPowerSaveAppIdWhitelist(); - } catch (RemoteException e) { - return new int[0]; - } - } - public void registerListener(INetworkPolicyListener listener) { try { mService.registerListener(listener); diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl new file mode 100644 index 000000000000..3cb29ff91c6b --- /dev/null +++ b/core/java/android/os/IDeviceIdleController.aidl @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2015, 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.os; + +/** @hide */ +interface IDeviceIdleController { + void addPowerSaveWhitelistApp(String name); + void removePowerSaveWhitelistApp(String name); + String[] getSystemPowerWhitelist(); + String[] getFullPowerWhitelist(); + int[] getAppIdWhitelist(); +} diff --git a/core/java/android/os/IPermissionController.aidl b/core/java/android/os/IPermissionController.aidl index 73a68f1aa4a7..0cc160309bd8 100644 --- a/core/java/android/os/IPermissionController.aidl +++ b/core/java/android/os/IPermissionController.aidl @@ -20,4 +20,5 @@ package android.os; /** @hide */ interface IPermissionController { boolean checkPermission(String permission, int pid, int uid); + String[] getPackagesForUid(int uid); } diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 01c9a21441ab..1d9d7d2191ae 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -920,6 +920,14 @@ public final class PowerManager { = "android.os.action.DEVICE_IDLE_MODE_CHANGED"; /** + * @hide Intent that is broadcast when the set of power save whitelist apps has changed. + * This broadcast is only sent to registered receivers. + */ + @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_POWER_SAVE_WHITELIST_CHANGED + = "android.os.action.POWER_SAVE_WHITELIST_CHANGED"; + + /** * Intent that is broadcast when the state of {@link #isPowerSaveMode()} is about to change. * This broadcast is only sent to registered receivers. * diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index 16e0bf7476c9..fcde3f4c55c7 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -942,6 +942,24 @@ public interface IMountService extends IInterface { } @Override + public VolumeRecord[] getVolumeRecords(int _flags) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + VolumeRecord[] _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeInt(_flags); + mRemote.transact(Stub.TRANSACTION_getVolumeRecords, _data, _reply, 0); + _reply.readException(); + _result = _reply.createTypedArray(VolumeRecord.CREATOR); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + @Override public void mount(String volId) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); @@ -1033,12 +1051,12 @@ public interface IMountService extends IInterface { } @Override - public void setVolumeNickname(String volId, String nickname) throws RemoteException { + public void setVolumeNickname(String fsUuid, String nickname) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); - _data.writeString(volId); + _data.writeString(fsUuid); _data.writeString(nickname); mRemote.transact(Stub.TRANSACTION_setVolumeNickname, _data, _reply, 0); _reply.readException(); @@ -1049,12 +1067,12 @@ public interface IMountService extends IInterface { } @Override - public void setVolumeUserFlags(String volId, int flags, int mask) throws RemoteException { + public void setVolumeUserFlags(String fsUuid, int flags, int mask) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); - _data.writeString(volId); + _data.writeString(fsUuid); _data.writeInt(flags); _data.writeInt(mask); mRemote.transact(Stub.TRANSACTION_setVolumeUserFlags, _data, _reply, 0); @@ -1066,6 +1084,21 @@ public interface IMountService extends IInterface { } @Override + public void forgetVolume(String fsUuid) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(fsUuid); + mRemote.transact(Stub.TRANSACTION_forgetVolume, _data, _reply, 0); + _reply.readException(); + } finally { + _reply.recycle(); + _data.recycle(); + } + } + + @Override public String getPrimaryStorageUuid() throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); @@ -1192,20 +1225,22 @@ public interface IMountService extends IInterface { static final int TRANSACTION_getDisks = IBinder.FIRST_CALL_TRANSACTION + 44; static final int TRANSACTION_getVolumes = IBinder.FIRST_CALL_TRANSACTION + 45; + static final int TRANSACTION_getVolumeRecords = IBinder.FIRST_CALL_TRANSACTION + 46; - static final int TRANSACTION_mount = IBinder.FIRST_CALL_TRANSACTION + 46; - static final int TRANSACTION_unmount = IBinder.FIRST_CALL_TRANSACTION + 47; - static final int TRANSACTION_format = IBinder.FIRST_CALL_TRANSACTION + 48; + static final int TRANSACTION_mount = IBinder.FIRST_CALL_TRANSACTION + 47; + static final int TRANSACTION_unmount = IBinder.FIRST_CALL_TRANSACTION + 48; + static final int TRANSACTION_format = IBinder.FIRST_CALL_TRANSACTION + 49; - static final int TRANSACTION_partitionPublic = IBinder.FIRST_CALL_TRANSACTION + 49; - static final int TRANSACTION_partitionPrivate = IBinder.FIRST_CALL_TRANSACTION + 50; - static final int TRANSACTION_partitionMixed = IBinder.FIRST_CALL_TRANSACTION + 51; + static final int TRANSACTION_partitionPublic = IBinder.FIRST_CALL_TRANSACTION + 50; + static final int TRANSACTION_partitionPrivate = IBinder.FIRST_CALL_TRANSACTION + 51; + static final int TRANSACTION_partitionMixed = IBinder.FIRST_CALL_TRANSACTION + 52; - static final int TRANSACTION_setVolumeNickname = IBinder.FIRST_CALL_TRANSACTION + 52; - static final int TRANSACTION_setVolumeUserFlags = IBinder.FIRST_CALL_TRANSACTION + 53; + static final int TRANSACTION_setVolumeNickname = IBinder.FIRST_CALL_TRANSACTION + 53; + static final int TRANSACTION_setVolumeUserFlags = IBinder.FIRST_CALL_TRANSACTION + 54; + static final int TRANSACTION_forgetVolume = IBinder.FIRST_CALL_TRANSACTION + 55; - static final int TRANSACTION_getPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 54; - static final int TRANSACTION_setPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 55; + static final int TRANSACTION_getPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 56; + static final int TRANSACTION_setPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 57; /** * Cast an IBinder object into an IMountService interface, generating a @@ -1647,6 +1682,14 @@ public interface IMountService extends IInterface { reply.writeTypedArray(volumes, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); return true; } + case TRANSACTION_getVolumeRecords: { + data.enforceInterface(DESCRIPTOR); + int _flags = data.readInt(); + VolumeRecord[] volumes = getVolumeRecords(_flags); + reply.writeNoException(); + reply.writeTypedArray(volumes, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + return true; + } case TRANSACTION_mount: { data.enforceInterface(DESCRIPTOR); String volId = data.readString(); @@ -1707,6 +1750,13 @@ public interface IMountService extends IInterface { reply.writeNoException(); return true; } + case TRANSACTION_forgetVolume: { + data.enforceInterface(DESCRIPTOR); + String fsUuid = data.readString(); + forgetVolume(fsUuid); + reply.writeNoException(); + return true; + } case TRANSACTION_getPrimaryStorageUuid: { data.enforceInterface(DESCRIPTOR); String volumeUuid = getPrimaryStorageUuid(); @@ -2012,6 +2062,7 @@ public interface IMountService extends IInterface { public DiskInfo[] getDisks() throws RemoteException; public VolumeInfo[] getVolumes(int flags) throws RemoteException; + public VolumeRecord[] getVolumeRecords(int flags) throws RemoteException; public void mount(String volId) throws RemoteException; public void unmount(String volId) throws RemoteException; @@ -2021,8 +2072,9 @@ public interface IMountService extends IInterface { public void partitionPrivate(String diskId) throws RemoteException; public void partitionMixed(String diskId, int ratio) throws RemoteException; - public void setVolumeNickname(String volId, String nickname) throws RemoteException; - public void setVolumeUserFlags(String volId, int flags, int mask) throws RemoteException; + public void setVolumeNickname(String fsUuid, String nickname) throws RemoteException; + public void setVolumeUserFlags(String fsUuid, int flags, int mask) throws RemoteException; + public void forgetVolume(String fsUuid) throws RemoteException; public String getPrimaryStorageUuid() throws RemoteException; public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) diff --git a/core/java/android/os/storage/IMountServiceListener.java b/core/java/android/os/storage/IMountServiceListener.java index fcb4779de324..2d13e497d010 100644 --- a/core/java/android/os/storage/IMountServiceListener.java +++ b/core/java/android/os/storage/IMountServiceListener.java @@ -93,8 +93,8 @@ public interface IMountServiceListener extends IInterface { } case TRANSACTION_onVolumeMetadataChanged: { data.enforceInterface(DESCRIPTOR); - final VolumeInfo vol = (VolumeInfo) data.readParcelable(null); - onVolumeMetadataChanged(vol); + final String fsUuid = data.readString(); + onVolumeMetadataChanged(fsUuid); reply.writeNoException(); return true; } @@ -192,12 +192,12 @@ public interface IMountServiceListener extends IInterface { } @Override - public void onVolumeMetadataChanged(VolumeInfo vol) throws RemoteException { + public void onVolumeMetadataChanged(String fsUuid) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); - _data.writeParcelable(vol, 0); + _data.writeString(fsUuid); mRemote.transact(Stub.TRANSACTION_onVolumeMetadataChanged, _data, _reply, android.os.IBinder.FLAG_ONEWAY); _reply.readException(); @@ -253,7 +253,7 @@ public interface IMountServiceListener extends IInterface { public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) throws RemoteException; - public void onVolumeMetadataChanged(VolumeInfo vol) throws RemoteException; + public void onVolumeMetadataChanged(String fsUuid) throws RemoteException; public void onDiskScanned(DiskInfo disk, int volumeCount) throws RemoteException; } diff --git a/core/java/android/os/storage/StorageEventListener.java b/core/java/android/os/storage/StorageEventListener.java index 6a0140e67a00..536aca9b12c9 100644 --- a/core/java/android/os/storage/StorageEventListener.java +++ b/core/java/android/os/storage/StorageEventListener.java @@ -41,7 +41,7 @@ public class StorageEventListener { public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) { } - public void onVolumeMetadataChanged(VolumeInfo vol) { + public void onVolumeMetadataChanged(String fsUuid) { } public void onDiskScanned(DiskInfo disk, int volumeCount) { diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 6116aef86ba5..29da4f1de64a 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -34,6 +34,7 @@ import android.os.ServiceManager; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; +import android.util.Slog; import android.util.SparseArray; import com.android.internal.os.SomeArgs; @@ -79,9 +80,6 @@ public class StorageManager { /** {@hide} */ public static final String UUID_PRIMARY_PHYSICAL = "primary_physical"; - /** {@hide} */ - public static final int FLAG_ALL_METADATA = 1 << 0; - private final Context mContext; private final ContentResolver mResolver; @@ -120,7 +118,7 @@ public class StorageManager { args.recycle(); return true; case MSG_VOLUME_METADATA_CHANGED: - mCallback.onVolumeMetadataChanged((VolumeInfo) args.arg1); + mCallback.onVolumeMetadataChanged((String) args.arg1); args.recycle(); return true; case MSG_DISK_SCANNED: @@ -156,9 +154,9 @@ public class StorageManager { } @Override - public void onVolumeMetadataChanged(VolumeInfo vol) { + public void onVolumeMetadataChanged(String fsUuid) { final SomeArgs args = SomeArgs.obtain(); - args.arg1 = vol; + args.arg1 = fsUuid; mHandler.obtainMessage(MSG_VOLUME_METADATA_CHANGED, args).sendToTarget(); } @@ -516,6 +514,18 @@ public class StorageManager { } /** {@hide} */ + public @Nullable VolumeRecord findRecordByUuid(String fsUuid) { + Preconditions.checkNotNull(fsUuid); + // TODO; go directly to service to make this faster + for (VolumeRecord rec : getVolumeRecords()) { + if (Objects.equals(rec.fsUuid, fsUuid)) { + return rec; + } + } + return null; + } + + /** {@hide} */ public @Nullable VolumeInfo findPrivateForEmulated(VolumeInfo emulatedVol) { return findVolumeById(emulatedVol.getId().replace("emulated", "private")); } @@ -527,13 +537,17 @@ public class StorageManager { /** {@hide} */ public @NonNull List<VolumeInfo> getVolumes() { - return getVolumes(0); + try { + return Arrays.asList(mMountService.getVolumes(0)); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } } /** {@hide} */ - public @NonNull List<VolumeInfo> getVolumes(int flags) { + public @NonNull List<VolumeRecord> getVolumeRecords() { try { - return Arrays.asList(mMountService.getVolumes(flags)); + return Arrays.asList(mMountService.getVolumeRecords(0)); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -541,13 +555,23 @@ public class StorageManager { /** {@hide} */ public @Nullable String getBestVolumeDescription(VolumeInfo vol) { - String descrip = vol.getDescription(); - if (vol.disk != null) { - if (TextUtils.isEmpty(descrip)) { - descrip = vol.disk.getDescription(); + // Nickname always takes precedence when defined + if (!TextUtils.isEmpty(vol.fsUuid)) { + final VolumeRecord rec = findRecordByUuid(vol.fsUuid); + if (!TextUtils.isEmpty(rec.nickname)) { + return rec.nickname; } } - return descrip; + + if (!TextUtils.isEmpty(vol.getDescription())) { + return vol.getDescription(); + } + + if (vol.disk != null) { + return vol.disk.getDescription(); + } + + return null; } /** {@hide} */ @@ -616,29 +640,62 @@ public class StorageManager { } /** {@hide} */ - public void setVolumeNickname(String volId, String nickname) { + public void wipeAdoptableDisks() { + // We only wipe devices in "adoptable" locations, which are in a + // long-term stable slot/location on the device, where apps have a + // reasonable chance of storing sensitive data. (Apps need to go through + // SAF to write to transient volumes.) + final List<DiskInfo> disks = getDisks(); + for (DiskInfo disk : disks) { + final String diskId = disk.getId(); + if (disk.isAdoptable()) { + Slog.d(TAG, "Found adoptable " + diskId + "; wiping"); + try { + // TODO: switch to explicit wipe command when we have it, + // for now rely on the fact that vfat format does a wipe + mMountService.partitionPublic(diskId); + } catch (Exception e) { + Slog.w(TAG, "Failed to wipe " + diskId + ", but soldiering onward", e); + } + } else { + Slog.d(TAG, "Ignorning non-adoptable disk " + disk.getId()); + } + } + } + + /** {@hide} */ + public void setVolumeNickname(String fsUuid, String nickname) { + try { + mMountService.setVolumeNickname(fsUuid, nickname); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /** {@hide} */ + public void setVolumeInited(String fsUuid, boolean inited) { try { - mMountService.setVolumeNickname(volId, nickname); + mMountService.setVolumeUserFlags(fsUuid, inited ? VolumeRecord.USER_FLAG_INITED : 0, + VolumeRecord.USER_FLAG_INITED); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } /** {@hide} */ - public void setVolumeInited(String volId, boolean inited) { + public void setVolumeSnoozed(String fsUuid, boolean snoozed) { try { - mMountService.setVolumeUserFlags(volId, inited ? VolumeInfo.USER_FLAG_INITED : 0, - VolumeInfo.USER_FLAG_INITED); + mMountService.setVolumeUserFlags(fsUuid, snoozed ? VolumeRecord.USER_FLAG_SNOOZED : 0, + VolumeRecord.USER_FLAG_SNOOZED); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } /** {@hide} */ - public void setVolumeSnoozed(String volId, boolean snoozed) { + public void forgetVolume(String fsUuid) { try { - mMountService.setVolumeUserFlags(volId, snoozed ? VolumeInfo.USER_FLAG_SNOOZED : 0, - VolumeInfo.USER_FLAG_SNOOZED); + mMountService.forgetVolume(fsUuid); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java index 4e9cfc77e5bd..fd10cae780e3 100644 --- a/core/java/android/os/storage/VolumeInfo.java +++ b/core/java/android/os/storage/VolumeInfo.java @@ -78,9 +78,6 @@ public class VolumeInfo implements Parcelable { public static final int MOUNT_FLAG_PRIMARY = 1 << 0; public static final int MOUNT_FLAG_VISIBLE = 1 << 1; - public static final int USER_FLAG_INITED = 1 << 0; - public static final int USER_FLAG_SNOOZED = 1 << 1; - private static SparseArray<String> sStateToEnvironment = new SparseArray<>(); private static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>(); @@ -135,8 +132,6 @@ public class VolumeInfo implements Parcelable { /** Framework state */ public final int mtpIndex; - public String nickname; - public int userFlags = 0; public VolumeInfo(String id, int type, DiskInfo disk, int mtpIndex) { this.id = Preconditions.checkNotNull(id); @@ -161,8 +156,6 @@ public class VolumeInfo implements Parcelable { fsLabel = parcel.readString(); path = parcel.readString(); mtpIndex = parcel.readInt(); - nickname = parcel.readString(); - userFlags = parcel.readInt(); } public static @NonNull String getEnvironmentForState(int state) { @@ -210,10 +203,6 @@ public class VolumeInfo implements Parcelable { return fsUuid; } - public @Nullable String getNickname() { - return nickname; - } - public int getMountUserId() { return mountUserId; } @@ -221,8 +210,6 @@ public class VolumeInfo implements Parcelable { public @Nullable String getDescription() { if (ID_PRIVATE_INTERNAL.equals(id)) { return Resources.getSystem().getString(com.android.internal.R.string.storage_internal); - } else if (!TextUtils.isEmpty(nickname)) { - return nickname; } else if (!TextUtils.isEmpty(fsLabel)) { return fsLabel; } else { @@ -250,14 +237,6 @@ public class VolumeInfo implements Parcelable { return (mountFlags & MOUNT_FLAG_VISIBLE) != 0; } - public boolean isInited() { - return (userFlags & USER_FLAG_INITED) != 0; - } - - public boolean isSnoozed() { - return (userFlags & USER_FLAG_SNOOZED) != 0; - } - public boolean isVisibleToUser(int userId) { if (type == TYPE_PUBLIC && userId == this.mountUserId) { return isVisible(); @@ -394,8 +373,6 @@ public class VolumeInfo implements Parcelable { pw.println(); pw.printPair("path", path); pw.printPair("mtpIndex", mtpIndex); - pw.printPair("nickname", nickname); - pw.printPair("userFlags", DebugUtils.flagsToString(getClass(), "USER_FLAG_", userFlags)); pw.decreaseIndent(); pw.println(); } @@ -461,7 +438,5 @@ public class VolumeInfo implements Parcelable { parcel.writeString(fsLabel); parcel.writeString(path); parcel.writeInt(mtpIndex); - parcel.writeString(nickname); - parcel.writeInt(userFlags); } } diff --git a/core/java/android/os/storage/VolumeRecord.java b/core/java/android/os/storage/VolumeRecord.java new file mode 100644 index 000000000000..096e2dd30cea --- /dev/null +++ b/core/java/android/os/storage/VolumeRecord.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2015 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.os.storage; + +import android.os.Parcel; +import android.os.Parcelable; +import android.util.DebugUtils; + +import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.Preconditions; + +import java.util.Objects; + +/** + * Metadata for a storage volume which may not be currently present. + * + * @hide + */ +public class VolumeRecord implements Parcelable { + public static final String EXTRA_FS_UUID = + "android.os.storage.extra.FS_UUID"; + + public static final int USER_FLAG_INITED = 1 << 0; + public static final int USER_FLAG_SNOOZED = 1 << 1; + + public final int type; + public final String fsUuid; + public String nickname; + public int userFlags; + + public VolumeRecord(int type, String fsUuid) { + this.type = type; + this.fsUuid = Preconditions.checkNotNull(fsUuid); + } + + public VolumeRecord(Parcel parcel) { + type = parcel.readInt(); + fsUuid = parcel.readString(); + nickname = parcel.readString(); + userFlags = parcel.readInt(); + } + + public int getType() { + return type; + } + + public String getFsUuid() { + return fsUuid; + } + + public String getNickname() { + return nickname; + } + + public boolean isInited() { + return (userFlags & USER_FLAG_INITED) != 0; + } + + public boolean isSnoozed() { + return (userFlags & USER_FLAG_SNOOZED) != 0; + } + + public void dump(IndentingPrintWriter pw) { + pw.println("VolumeRecord:"); + pw.increaseIndent(); + pw.printPair("type", DebugUtils.valueToString(VolumeInfo.class, "TYPE_", type)); + pw.printPair("fsUuid", fsUuid); + pw.printPair("nickname", nickname); + pw.printPair("userFlags", + DebugUtils.flagsToString(VolumeRecord.class, "USER_FLAG_", userFlags)); + pw.decreaseIndent(); + pw.println(); + } + + @Override + public VolumeRecord clone() { + final Parcel temp = Parcel.obtain(); + try { + writeToParcel(temp, 0); + temp.setDataPosition(0); + return CREATOR.createFromParcel(temp); + } finally { + temp.recycle(); + } + } + + @Override + public boolean equals(Object o) { + if (o instanceof VolumeRecord) { + return Objects.equals(fsUuid, ((VolumeRecord) o).fsUuid); + } else { + return false; + } + } + + @Override + public int hashCode() { + return fsUuid.hashCode(); + } + + public static final Creator<VolumeRecord> CREATOR = new Creator<VolumeRecord>() { + @Override + public VolumeRecord createFromParcel(Parcel in) { + return new VolumeRecord(in); + } + + @Override + public VolumeRecord[] newArray(int size) { + return new VolumeRecord[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(type); + parcel.writeString(fsUuid); + parcel.writeString(nickname); + parcel.writeInt(userFlags); + } +} diff --git a/core/java/android/security/keymaster/KeyCharacteristics.java b/core/java/android/security/keymaster/KeyCharacteristics.java index b3a3aada7ec4..458f1530dce0 100644 --- a/core/java/android/security/keymaster/KeyCharacteristics.java +++ b/core/java/android/security/keymaster/KeyCharacteristics.java @@ -105,11 +105,11 @@ public class KeyCharacteristics implements Parcelable { } } - public boolean getBoolean(KeyCharacteristics keyCharacteristics, int tag) { - if (keyCharacteristics.hwEnforced.containsTag(tag)) { - return keyCharacteristics.hwEnforced.getBoolean(tag, false); + public boolean getBoolean(int tag) { + if (hwEnforced.containsTag(tag)) { + return hwEnforced.getBoolean(tag, false); } else { - return keyCharacteristics.swEnforced.getBoolean(tag, false); + return swEnforced.getBoolean(tag, false); } } } diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index 14e947ce328b..dc8f3ea65c3c 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -62,7 +62,7 @@ public class ZenModeConfig implements Parcelable { Calendar.WEDNESDAY, Calendar.THURSDAY }; public static final int[] WEEKEND_DAYS = { Calendar.FRIDAY, Calendar.SATURDAY }; - public static final int[] MINUTE_BUCKETS = new int[] { 15, 30, 45, 60, 120, 180, 240, 480 }; + public static final int[] MINUTE_BUCKETS = generateMinuteBuckets(); private static final int SECONDS_MS = 1000; private static final int MINUTES_MS = 60 * SECONDS_MS; private static final int ZERO_VALUE_MS = 10 * SECONDS_MS; @@ -201,6 +201,18 @@ public class ZenModeConfig implements Parcelable { } } + private static int[] generateMinuteBuckets() { + final int maxHrs = 12; + final int[] buckets = new int[maxHrs + 3]; + buckets[0] = 15; + buckets[1] = 30; + buckets[2] = 45; + for (int i = 1; i <= maxHrs; i++) { + buckets[2 + i] = 60 * i; + } + return buckets; + } + public static String sourceToString(int source) { switch (source) { case SOURCE_ANYONE: @@ -298,10 +310,10 @@ public class ZenModeConfig implements Parcelable { throw new IndexOutOfBoundsException("bad source in config:" + rt.allowFrom); } } else if (MANUAL_TAG.equals(tag)) { - rt.manualRule = readRuleXml(parser); + rt.manualRule = readRuleXml(parser, false /*conditionRequired*/); } else if (AUTOMATIC_TAG.equals(tag)) { final String id = parser.getAttributeValue(null, RULE_ATT_ID); - final ZenRule automaticRule = readRuleXml(parser); + final ZenRule automaticRule = readRuleXml(parser, true /*conditionRequired*/); if (id != null && automaticRule != null) { rt.automaticRules.put(id, automaticRule); } @@ -341,7 +353,7 @@ public class ZenModeConfig implements Parcelable { out.endTag(null, ZEN_TAG); } - public static ZenRule readRuleXml(XmlPullParser parser) { + public static ZenRule readRuleXml(XmlPullParser parser, boolean conditionRequired) { final ZenRule rt = new ZenRule(); rt.enabled = safeBoolean(parser, RULE_ATT_ENABLED, true); rt.snoozing = safeBoolean(parser, RULE_ATT_SNOOZING, false); @@ -355,7 +367,7 @@ public class ZenModeConfig implements Parcelable { rt.conditionId = safeUri(parser, RULE_ATT_CONDITION_ID); rt.component = safeComponentName(parser, RULE_ATT_COMPONENT); rt.condition = readConditionXml(parser); - return rt.condition != null ? rt : null; + return rt.condition != null || !conditionRequired ? rt : null; } public static void writeRuleXml(ZenRule rule, XmlSerializer out) throws IOException { diff --git a/core/java/android/speech/RecognizerIntent.java b/core/java/android/speech/RecognizerIntent.java index e991d84807c1..ce94315c4225 100644 --- a/core/java/android/speech/RecognizerIntent.java +++ b/core/java/android/speech/RecognizerIntent.java @@ -403,4 +403,12 @@ public class RecognizerIntent { */ public static final String EXTRA_SUPPORTED_LANGUAGES = "android.speech.extra.SUPPORTED_LANGUAGES"; + + /** + * Optional boolean, to be used with {@link #ACTION_RECOGNIZE_SPEECH}, + * {@link #ACTION_VOICE_SEARCH_HANDS_FREE}, {@link #ACTION_WEB_SEARCH} to indicate whether to + * only use an offline speech recognition engine. The default is false, meaning that either + * network or offline recognition engines may be used. + */ + public static final String EXTRA_PREFER_OFFLINE = "android.speech.extra.PREFER_OFFLINE"; } diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java index aefced8a6260..558b8f558236 100644 --- a/core/java/android/util/EventLog.java +++ b/core/java/android/util/EventLog.java @@ -74,6 +74,7 @@ public class EventLog { private static final byte LONG_TYPE = 1; private static final byte STRING_TYPE = 2; private static final byte LIST_TYPE = 3; + private static final byte FLOAT_TYPE = 4; /** @param data containing event, read from the system */ /*package*/ Event(byte[] data) { @@ -106,7 +107,7 @@ public class EventLog { return mBuffer.getInt(offset); } - /** @return one of Integer, Long, String, null, or Object[] of same. */ + /** @return one of Integer, Long, Float, String, null, or Object[] of same. */ public synchronized Object getData() { try { int offset = mBuffer.getShort(HEADER_SIZE_OFFSET); @@ -130,10 +131,13 @@ public class EventLog { byte type = mBuffer.get(); switch (type) { case INT_TYPE: - return (Integer) mBuffer.getInt(); + return mBuffer.getInt(); case LONG_TYPE: - return (Long) mBuffer.getLong(); + return mBuffer.getLong(); + + case FLOAT_TYPE: + return mBuffer.getFloat(); case STRING_TYPE: try { @@ -180,6 +184,14 @@ public class EventLog { /** * Record an event log message. * @param tag The event type tag code + * @param value A value to log + * @return The number of bytes written + */ + public static native int writeEvent(int tag, float value); + + /** + * Record an event log message. + * @param tag The event type tag code * @param str A value to log * @return The number of bytes written */ diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index ad34f020fa9d..6db46e9fda0d 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -284,11 +284,6 @@ public class TextureView extends View { return LAYER_TYPE_HARDWARE; } - @Override - boolean hasStaticLayer() { - return true; - } - /** * Calling this method has no effect. */ diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index fa74797e6a51..b5b7f0feede4 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -14373,15 +14373,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Indicates whether this view has a static layer. A view with layer type - * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are - * dynamic. - */ - boolean hasStaticLayer() { - return true; - } - - /** * Indicates what type of layer is currently associated with this view. By default * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}. * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)} @@ -15499,12 +15490,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (drawingWithRenderNode) { renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha()); } else if (layerType == LAYER_TYPE_NONE) { - int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; - if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0) { - layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG; - } canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(), - multipliedAlpha, layerFlags); + multipliedAlpha); } } else { // Alpha is handled by the child directly, clobber the layer's alpha diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 4324e752eb4d..d0d42010b3ec 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -3505,8 +3505,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final View[] children = mChildren; for (int i = 0; i < count; i++) { final View child = children[i]; - if (((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) && - child.hasStaticLayer()) { + if (((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null)) { recreateChildDisplayList(child); } } diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java index 478fa00d4607..d271af28b037 100644 --- a/core/java/android/widget/DayPickerPagerAdapter.java +++ b/core/java/android/widget/DayPickerPagerAdapter.java @@ -286,14 +286,10 @@ class DayPickerPagerAdapter extends PagerAdapter { return null; } - private boolean isCalendarInRange(Calendar value) { - return value.compareTo(mMinDate) >= 0 && value.compareTo(mMaxDate) <= 0; - } - private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() { @Override public void onDayClick(SimpleMonthView view, Calendar day) { - if (day != null && isCalendarInRange(day)) { + if (day != null) { setSelectedDay(day); if (mOnDaySelectedListener != null) { diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java index 113e597bedfd..334afab6edd3 100644 --- a/core/java/android/widget/DayPickerView.java +++ b/core/java/android/widget/DayPickerView.java @@ -178,6 +178,13 @@ class DayPickerView extends ViewGroup { }); } + private void updateButtonVisibility(int position) { + final boolean hasPrev = position > 0; + final boolean hasNext = position < (mAdapter.getCount() - 1); + mPrevButton.setVisibility(hasPrev ? View.VISIBLE : View.INVISIBLE); + mNextButton.setVisibility(hasNext ? View.VISIBLE : View.INVISIBLE); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final ViewPager viewPager = mViewPager; @@ -218,12 +225,6 @@ class DayPickerView extends ViewGroup { final int height = bottom - top; mViewPager.layout(0, 0, width, height); - if (mViewPager.getChildCount() < 1) { - leftButton.setVisibility(View.INVISIBLE); - rightButton.setVisibility(View.INVISIBLE); - return; - } - final SimpleMonthView monthView = (SimpleMonthView) mViewPager.getChildAt(0); final int monthHeight = monthView.getMonthHeight(); final int cellWidth = monthView.getCellWidth(); @@ -235,7 +236,6 @@ class DayPickerView extends ViewGroup { final int leftIconTop = monthView.getPaddingTop() + (monthHeight - leftDH) / 2; final int leftIconLeft = monthView.getPaddingLeft() + (cellWidth - leftDW) / 2; leftButton.layout(leftIconLeft, leftIconTop, leftIconLeft + leftDW, leftIconTop + leftDH); - leftButton.setVisibility(View.VISIBLE); final int rightDW = rightButton.getMeasuredWidth(); final int rightDH = rightButton.getMeasuredHeight(); @@ -243,7 +243,6 @@ class DayPickerView extends ViewGroup { final int rightIconRight = width - monthView.getPaddingRight() - (cellWidth - rightDW) / 2; rightButton.layout(rightIconRight - rightDW, rightIconTop, rightIconRight, rightIconTop + rightDH); - rightButton.setVisibility(View.VISIBLE); } public void setDayOfWeekTextAppearance(int resId) { @@ -399,10 +398,7 @@ class DayPickerView extends ViewGroup { @Override public void onPageSelected(int position) { - mPrevButton.setVisibility( - position > 0 ? View.VISIBLE : View.INVISIBLE); - mNextButton.setVisibility( - position < (mAdapter.getCount() - 1) ? View.VISIBLE : View.INVISIBLE); + updateButtonVisibility(position); } }; diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 089074a36fa9..35e73892a6ea 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -62,7 +62,6 @@ import android.text.TextUtils; import android.text.method.KeyListener; import android.text.method.MetaKeyKeyListener; import android.text.method.MovementMethod; -import android.text.method.PasswordTransformationMethod; import android.text.method.WordIterator; import android.text.style.EasyEditSpan; import android.text.style.SuggestionRangeSpan; @@ -682,34 +681,6 @@ public class Editor { } } - /** - * Unlike {@link TextView#textCanBeSelected()}, this method is based on the <i>current</i> state - * of the TextView. textCanBeSelected() has to be true (this is one of the conditions to have - * a selection controller (see {@link #prepareCursorControllers()}), but this is not sufficient. - */ - private boolean canSelectText() { - return hasSelectionController() && mTextView.getText().length() != 0; - } - - /** - * It would be better to rely on the input type for everything. A password inputType should have - * a password transformation. We should hence use isPasswordInputType instead of this method. - * - * We should: - * - Call setInputType in setKeyListener instead of changing the input type directly (which - * would install the correct transformation). - * - Refuse the installation of a non-password transformation in setTransformation if the input - * type is password. - * - * However, this is like this for legacy reasons and we cannot break existing apps. This method - * is useful since it matches what the user can see (obfuscated text or not). - * - * @return true if the current transformation method is of the password type. - */ - private boolean hasPasswordTransformationMethod() { - return mTextView.getTransformationMethod() instanceof PasswordTransformationMethod; - } - private int getWordStart(int offset) { // FIXME - For this and similar methods we're not doing anything to check if there's // a LocaleSpan in the text, this may be something we should try handling or checking for. @@ -758,11 +729,11 @@ public class Editor { * successfully performed. */ private boolean selectCurrentWord() { - if (!canSelectText()) { + if (!mTextView.canSelectText()) { return false; } - if (hasPasswordTransformationMethod()) { + if (mTextView.hasPasswordTransformationMethod()) { // Always select all on a password field. // Cut/copy menu entries are not available for passwords, but being able to select all // is however useful to delete or paste to replace the entire content. @@ -1717,7 +1688,7 @@ public class Editor { return false; } - if (!canSelectText() || !mTextView.requestFocus()) { + if (!mTextView.canSelectText() || !mTextView.requestFocus()) { Log.w(TextView.LOG_TAG, "TextView does not support text selection. Action mode cancelled."); return false; @@ -3089,7 +3060,7 @@ public class Editor { MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); } - if (canSelectText() && !hasPasswordTransformationMethod()) { + if (mTextView.canSelectAllText()) { menu.add(0, TextView.ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll). setAlphabeticShortcut('a'). setShowAsAction( @@ -3846,6 +3817,10 @@ public class Editor { startSelectionActionModeWithoutSelection(); } } + } else { + if (mSelectionActionMode != null) { + mSelectionActionMode.invalidateContentRect(); + } } hideAfterDelay(); break; diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java index 2778f0f9df7d..acf1df931798 100644 --- a/core/java/android/widget/SimpleMonthView.java +++ b/core/java/android/widget/SimpleMonthView.java @@ -31,6 +31,7 @@ import android.text.TextPaint; import android.text.format.DateFormat; import android.util.AttributeSet; import android.util.IntArray; +import android.util.MathUtils; import android.util.StateSet; import android.view.MotionEvent; import android.view.View; @@ -422,7 +423,8 @@ class SimpleMonthView extends View { int stateMask = 0; - if (day >= mEnabledDayStart && day <= mEnabledDayEnd) { + final boolean isDayEnabled = isDayEnabled(day); + if (isDayEnabled) { stateMask |= StateSet.VIEW_STATE_ENABLED; } @@ -435,8 +437,11 @@ class SimpleMonthView extends View { } else if (mTouchedItem == day) { stateMask |= StateSet.VIEW_STATE_PRESSED; - // Adjust the circle to be centered on the row. - canvas.drawCircle(colCenterRtl, rowCenter, mDaySelectorRadius, mDayHighlightPaint); + if (isDayEnabled) { + // Adjust the circle to be centered on the row. + canvas.drawCircle(colCenterRtl, rowCenter, + mDaySelectorRadius, mDayHighlightPaint); + } } final boolean isDayToday = mToday == day; @@ -460,6 +465,14 @@ class SimpleMonthView extends View { } } + private boolean isDayEnabled(int day) { + return day >= mEnabledDayStart && day <= mEnabledDayEnd; + } + + private boolean isValidDayOfMonth(int day) { + return day >= 1 && day <= mDaysInMonth; + } + private static boolean isValidDayOfWeek(int day) { return day >= Calendar.SUNDAY && day <= Calendar.SATURDAY; } @@ -536,13 +549,6 @@ class SimpleMonthView extends View { mWeekStart = mCalendar.getFirstDayOfWeek(); } - if (enabledDayStart > 0 && enabledDayEnd < 32) { - mEnabledDayStart = enabledDayStart; - } - if (enabledDayEnd > 0 && enabledDayEnd < 32 && enabledDayEnd >= enabledDayStart) { - mEnabledDayEnd = enabledDayEnd; - } - // Figure out what day today is. final Calendar today = Calendar.getInstance(); mToday = -1; @@ -554,6 +560,9 @@ class SimpleMonthView extends View { } } + mEnabledDayStart = MathUtils.constrain(enabledDayStart, 1, mDaysInMonth); + mEnabledDayEnd = MathUtils.constrain(enabledDayEnd, mEnabledDayStart, mDaysInMonth); + // Invalidate the old title. mTitle = null; @@ -694,7 +703,7 @@ class SimpleMonthView extends View { final int col = (paddedXRtl * DAYS_IN_WEEK) / mPaddedWidth; final int index = col + row * DAYS_IN_WEEK; final int day = index + 1 - findDayOffset(); - if (day < 1 || day > mDaysInMonth) { + if (!isValidDayOfMonth(day)) { return -1; } @@ -708,7 +717,7 @@ class SimpleMonthView extends View { * @param outBounds the rect to populate with bounds */ private boolean getBoundsForDay(int id, Rect outBounds) { - if (id < 1 || id > mDaysInMonth) { + if (!isValidDayOfMonth(id)) { return false; } @@ -742,7 +751,7 @@ class SimpleMonthView extends View { * @param day the day that was clicked */ private boolean onDayClicked(int day) { - if (day < 0 || day > mDaysInMonth) { + if (!isValidDayOfMonth(day) || !isDayEnabled(day)) { return false; } @@ -774,7 +783,7 @@ class SimpleMonthView extends View { @Override protected int getVirtualViewAt(float x, float y) { final int day = getDayAtLocation((int) (x + 0.5f), (int) (y + 0.5f)); - if (day >= 0) { + if (day != -1) { return day; } return ExploreByTouchHelper.INVALID_ID; @@ -808,7 +817,13 @@ class SimpleMonthView extends View { node.setText(getDayText(virtualViewId)); node.setContentDescription(getDayDescription(virtualViewId)); node.setBoundsInParent(mTempRect); - node.addAction(AccessibilityAction.ACTION_CLICK); + + final boolean isDayEnabled = isDayEnabled(virtualViewId); + if (isDayEnabled) { + node.addAction(AccessibilityAction.ACTION_CLICK); + } + + node.setEnabled(isDayEnabled); if (virtualViewId == mActivatedDay) { // TODO: This should use activated once that's supported. @@ -835,7 +850,7 @@ class SimpleMonthView extends View { * @return a description of the virtual view */ private CharSequence getDayDescription(int id) { - if (id >= 1 && id <= mDaysInMonth) { + if (isValidDayOfMonth(id)) { mTempCalendar.set(mYear, mMonth, id); return DateFormat.format(DATE_FORMAT, mTempCalendar.getTimeInMillis()); } @@ -850,7 +865,7 @@ class SimpleMonthView extends View { * @return the visible text of the virtual view */ private CharSequence getDayText(int id) { - if (id >= 1 && id <= mDaysInMonth) { + if (isValidDayOfMonth(id)) { return Integer.toString(id); } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 8ce5f08d4c20..774a864483ae 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -4569,7 +4569,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @return true if the current transformation method is of the password type. */ - private boolean hasPasswordTransformationMethod() { + boolean hasPasswordTransformationMethod() { return mTransformation instanceof PasswordTransformationMethod; } @@ -8583,7 +8583,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * a selection controller (see {@link Editor#prepareCursorControllers()}), but this is not * sufficient. */ - private boolean canSelectText() { + boolean canSelectText() { return mText.length() != 0 && mEditor != null && mEditor.hasSelectionController(); } @@ -9199,6 +9199,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return false; } + boolean canSelectAllText() { + return canSelectText() && !hasPasswordTransformationMethod(); + } + boolean selectAllText() { // Need to hide insert point cursor controller before settings selection, otherwise insert // point cursor controller obtains cursor update event and update cursor with cancelling diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 2b77b2c36e17..e347faa48fb9 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -405,8 +405,10 @@ public class ChooserActivity extends ResolverActivity { int launchedFromUid, boolean filterLastUsed, ChooserTarget[] callerChooserTargets) { super(context, initialIntents, rList, launchedFromUid, filterLastUsed); - for (ChooserTarget target : callerChooserTargets) { - mCallerTargets.add(new ChooserTargetInfo(target)); + if (callerChooserTargets != null) { + for (ChooserTarget target : callerChooserTargets) { + mCallerTargets.add(new ChooserTargetInfo(target)); + } } } diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java index eff44bd1c87f..481ab0e5be31 100644 --- a/core/java/com/android/internal/content/PackageMonitor.java +++ b/core/java/com/android/internal/content/PackageMonitor.java @@ -44,7 +44,6 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { sPackageFilt.addAction(Intent.ACTION_PACKAGE_CHANGED); sPackageFilt.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); sPackageFilt.addAction(Intent.ACTION_PACKAGE_RESTARTED); - sPackageFilt.addAction(Intent.ACTION_UID_REMOVED); sPackageFilt.addDataScheme("package"); sNonDataFilt.addAction(Intent.ACTION_UID_REMOVED); sNonDataFilt.addAction(Intent.ACTION_USER_STOPPED); diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index 3a1e0caed2eb..3f7696fa8c34 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -438,6 +438,9 @@ public final class FloatingToolbar { // Make sure a panel is set as the content. if (mContentContainer.getChildCount() == 0) { setMainPanelAsContent(); + // If we're yet to show the popup, set the container visibility to zero. + // The "show" animation will make this visible. + mContentContainer.setAlpha(0); } preparePopupContent(); mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, x, y); @@ -478,7 +481,7 @@ public final class FloatingToolbar { * Returns {@code true} if this popup is currently showing. {@code false} otherwise. */ public boolean isShowing() { - return mPopupWindow.isShowing() && !mDismissed && !mHidden; + return !mDismissed && !mHidden; } /** @@ -494,7 +497,7 @@ public final class FloatingToolbar { * This is a no-op if this popup is not showing. */ public void updateCoordinates(int x, int y) { - if (!isShowing()) { + if (!isShowing() || !mPopupWindow.isShowing()) { return; } diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index c384ef9785e4..6afb226df1ac 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -26,6 +26,8 @@ #include <utils/Log.h> #include <media/AudioRecord.h> +#include <ScopedUtfChars.h> + #include "android_media_AudioFormat.h" #include "android_media_AudioErrors.h" @@ -146,7 +148,7 @@ static sp<AudioRecord> setAudioRecord(JNIEnv* env, jobject thiz, const sp<AudioR static jint android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this, jobject jaa, jint sampleRateInHertz, jint channelMask, jint channelIndexMask, - jint audioFormat, jint buffSizeInBytes, jintArray jSession) + jint audioFormat, jint buffSizeInBytes, jintArray jSession, jstring opPackageName) { //ALOGV(">> Entering android_media_AudioRecord_setup"); //ALOGV("sampleRate=%d, audioFormat=%d, channel mask=%x, buffSizeInBytes=%d", @@ -208,8 +210,10 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this, env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); nSession = NULL; + ScopedUtfChars opPackageNameStr(env, opPackageName); + // create an uninitialized AudioRecord object - sp<AudioRecord> lpRecorder = new AudioRecord(); + sp<AudioRecord> lpRecorder = new AudioRecord(String16(opPackageNameStr.c_str())); audio_attributes_t *paa = NULL; // read the AudioAttributes values @@ -597,7 +601,7 @@ static JNINativeMethod gMethods[] = { // name, signature, funcPtr {"native_start", "(II)I", (void *)android_media_AudioRecord_start}, {"native_stop", "()V", (void *)android_media_AudioRecord_stop}, - {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;IIIII[I)I", + {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;IIIII[ILjava/lang/String;)I", (void *)android_media_AudioRecord_setup}, {"native_finalize", "()V", (void *)android_media_AudioRecord_finalize}, {"native_release", "()V", (void *)android_media_AudioRecord_release}, diff --git a/core/jni/android_media_RemoteDisplay.cpp b/core/jni/android_media_RemoteDisplay.cpp index e2bba30d1d66..9bc223b57a42 100644 --- a/core/jni/android_media_RemoteDisplay.cpp +++ b/core/jni/android_media_RemoteDisplay.cpp @@ -134,8 +134,10 @@ private: // ---------------------------------------------------------------------------- -static jlong nativeListen(JNIEnv* env, jobject remoteDisplayObj, jstring ifaceStr) { +static jlong nativeListen(JNIEnv* env, jobject remoteDisplayObj, jstring ifaceStr, + jstring opPackageNameStr) { ScopedUtfChars iface(env, ifaceStr); + ScopedUtfChars opPackageName(env, opPackageNameStr); sp<IServiceManager> sm = defaultServiceManager(); sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>( @@ -146,7 +148,7 @@ static jlong nativeListen(JNIEnv* env, jobject remoteDisplayObj, jstring ifaceSt } sp<NativeRemoteDisplayClient> client(new NativeRemoteDisplayClient(env, remoteDisplayObj)); - sp<IRemoteDisplay> display = service->listenForRemoteDisplay( + sp<IRemoteDisplay> display = service->listenForRemoteDisplay(String16(opPackageName.c_str()), client, String8(iface.c_str())); if (display == NULL) { ALOGE("Media player service rejected request to listen for remote display '%s'.", @@ -176,7 +178,7 @@ static void nativeDispose(JNIEnv* env, jobject remoteDisplayObj, jlong ptr) { // ---------------------------------------------------------------------------- static JNINativeMethod gMethods[] = { - {"nativeListen", "(Ljava/lang/String;)J", + {"nativeListen", "(Ljava/lang/String;Ljava/lang/String;)J", (void*)nativeListen }, {"nativeDispose", "(J)V", (void*)nativeDispose }, diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index cfbeddacdffb..fb8207553ece 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -200,10 +200,8 @@ static void report_exception(JNIEnv* env, jthrowable excep, const char* msg) * that can be made while an exception is pending, so we want to * get the VM ptr, throw the exception, and then detach the thread. */ - JavaVM* vm = jnienv_to_javavm(env); env->Throw(excep); - vm->DetachCurrentThread(); - sleep(60); + env->ExceptionDescribe(); ALOGE("Forcefully exiting"); exit(1); } diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp index 5cb8b2e9e5f4..05bc12563b6c 100644 --- a/core/jni/android_util_EventLog.cpp +++ b/core/jni/android_util_EventLog.cpp @@ -40,6 +40,9 @@ static jfieldID gIntegerValueID; static jclass gLongClass; static jfieldID gLongValueID; +static jclass gFloatClass; +static jfieldID gFloatValueID; + static jclass gStringClass; /* @@ -66,6 +69,17 @@ static jint android_util_EventLog_writeEvent_Long(JNIEnv* env UNUSED, /* * In class android.util.EventLog: + * static native int writeEvent(long tag, float value) + */ +static jint android_util_EventLog_writeEvent_Float(JNIEnv* env UNUSED, + jobject clazz UNUSED, + jint tag, jfloat value) +{ + return android_btWriteLog(tag, EVENT_TYPE_FLOAT, &value, sizeof(value)); +} + +/* + * In class android.util.EventLog: * static native int writeEvent(int tag, String value) */ static jint android_util_EventLog_writeEvent_String(JNIEnv* env, @@ -128,6 +142,12 @@ static jint android_util_EventLog_writeEvent_Array(JNIEnv* env, jobject clazz, buf[pos++] = EVENT_TYPE_LONG; memcpy(&buf[pos], &longVal, sizeof(longVal)); pos += sizeof(longVal); + } else if (env->IsInstanceOf(item, gFloatClass)) { + jfloat floatVal = env->GetFloatField(item, gFloatValueID); + if (pos + 1 + sizeof(floatVal) > max) break; + buf[pos++] = EVENT_TYPE_FLOAT; + memcpy(&buf[pos], &floatVal, sizeof(floatVal)); + pos += sizeof(floatVal); } else { jniThrowException(env, "java/lang/IllegalArgumentException", @@ -233,6 +253,7 @@ static JNINativeMethod gRegisterMethods[] = { /* name, signature, funcPtr */ { "writeEvent", "(II)I", (void*) android_util_EventLog_writeEvent_Integer }, { "writeEvent", "(IJ)I", (void*) android_util_EventLog_writeEvent_Long }, + { "writeEvent", "(IF)I", (void*) android_util_EventLog_writeEvent_Float }, { "writeEvent", "(ILjava/lang/String;)I", (void*) android_util_EventLog_writeEvent_String @@ -251,6 +272,7 @@ static struct { const char *name; jclass *clazz; } gClasses[] = { { "android/util/EventLog$Event", &gEventClass }, { "java/lang/Integer", &gIntegerClass }, { "java/lang/Long", &gLongClass }, + { "java/lang/Float", &gFloatClass }, { "java/lang/String", &gStringClass }, { "java/util/Collection", &gCollectionClass }, }; @@ -258,6 +280,7 @@ static struct { const char *name; jclass *clazz; } gClasses[] = { static struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = { { &gIntegerClass, "value", "I", &gIntegerValueID }, { &gLongClass, "value", "J", &gLongValueID }, + { &gFloatClass, "value", "F", &gFloatValueID }, }; static struct { jclass *c; const char *name, *mt; jmethodID *id; } gMethods[] = { diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 018c1a1b6ed5..942e6a68b386 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -79,6 +79,8 @@ <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" /> <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" /> + <protected-broadcast android:name="android.os.action.DEVICE_IDLE_MODE_CHANGED" /> + <protected-broadcast android:name="android.os.action.POWER_SAVE_WHITELIST_CHANGED" /> <protected-broadcast android:name="android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED" /> @@ -1178,13 +1180,13 @@ <permission android:name="android.permission.REGISTER_CONNECTION_MANAGER" android:protectionLevel="system|signature" /> - <!-- @SystemApi Allows an application to bind to InCallService implementations. - @hide --> + <!-- Must be required by a {@link android.telecom.InCallService}, + to ensure that only the system can bind to it. --> <permission android:name="android.permission.BIND_INCALL_SERVICE" android:protectionLevel="system|signature" /> - <!-- @SystemApi Allows an application to bind to ConnectionService implementations. - @hide --> + <!-- Must be required by a {@link android.telecom.ConnectionService}, + to ensure that only the system can bind to it. --> <permission android:name="android.permission.BIND_CONNECTION_SERVICE" android:protectionLevel="system|signature" /> diff --git a/core/res/res/color/primary_text_activated_material_dark.xml b/core/res/res/color/primary_text_inverse_when_activated_material.xml index f1b742ac4834..0f7f9cdf9bef 100644 --- a/core/res/res/color/primary_text_activated_material_dark.xml +++ b/core/res/res/color/primary_text_inverse_when_activated_material.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2014 The Android Open Source Project +<!-- Copyright (C) 2015 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. @@ -15,7 +15,18 @@ --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_activated="true" - android:color="@color/primary_text_default_material_light"/> - <item android:color="@color/primary_text_default_material_dark"/> + <item + android:state_enabled="false" + android:state_activated="true" + android:color="?attr/textColorPrimaryInverse" + android:alpha="?attr/disabledAlpha" /> + <item + android:state_enabled="false" + android:color="?attr/textColorPrimary" + android:alpha="?attr/disabledAlpha" /> + <item + android:state_activated="true" + android:color="?attr/textColorPrimaryInverse" /> + <item + android:color="?attr/textColorPrimary" /> </selector> diff --git a/core/res/res/color/secondary_text_activated_material_dark.xml b/core/res/res/color/secondary_text_activated_material_dark.xml deleted file mode 100644 index 7a8428a03d8a..000000000000 --- a/core/res/res/color/secondary_text_activated_material_dark.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2014 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. ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_activated="true" - android:color="@color/secondary_text_default_material_light"/> - <item android:color="@color/secondary_text_default_material_dark"/> -</selector> diff --git a/core/res/res/color/secondary_text_activated_material_light.xml b/core/res/res/color/secondary_text_activated_material_light.xml deleted file mode 100644 index 36ff408a79ac..000000000000 --- a/core/res/res/color/secondary_text_activated_material_light.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2014 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. ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_activated="true" - android:color="@color/secondary_text_default_material_dark"/> - <item android:color="@color/secondary_text_default_material_light"/> -</selector> diff --git a/core/res/res/color/primary_text_activated_material_light.xml b/core/res/res/color/secondary_text_inverse_when_activated_material.xml index d92da631c937..5b259de560f1 100644 --- a/core/res/res/color/primary_text_activated_material_light.xml +++ b/core/res/res/color/secondary_text_inverse_when_activated_material.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2014 The Android Open Source Project +<!-- Copyright (C) 2015 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. @@ -15,7 +15,18 @@ --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_activated="true" - android:color="@color/primary_text_default_material_dark"/> - <item android:color="@color/primary_text_default_material_light"/> + <item + android:state_enabled="false" + android:state_activated="true" + android:color="?attr/textColorSecondaryInverse" + android:alpha="?attr/disabledAlpha" /> + <item + android:state_enabled="false" + android:color="?attr/textColorSecondary" + android:alpha="?attr/disabledAlpha" /> + <item + android:state_activated="true" + android:color="?attr/textColorSecondaryInverse" /> + <item + android:color="?attr/textColorSecondary" /> </selector> diff --git a/core/res/res/drawable/btn_check_material_anim.xml b/core/res/res/drawable/btn_check_material_anim.xml index 41caa4ece032..7cb1b89904b6 100644 --- a/core/res/res/drawable/btn_check_material_anim.xml +++ b/core/res/res/drawable/btn_check_material_anim.xml @@ -15,15 +15,24 @@ --> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_checked="true" android:id="@+id/on" + + <item + android:id="@+id/on" + android:state_checked="true" android:drawable="@drawable/ic_checkbox_checked" /> - <item android:id="@+id/off" + + <item + android:id="@+id/off" android:drawable="@drawable/ic_checkbox_unchecked" /> - <transition android:fromId="@+id/off" android:toId="@+id/on" + <transition + android:fromId="@+id/off" + android:toId="@+id/on" android:drawable="@drawable/ic_checkbox_unchecked_animation" /> - <transition android:fromId="@+id/on" android:toId="@+id/off" + <transition + android:fromId="@+id/on" + android:toId="@+id/off" android:drawable="@drawable/ic_checkbox_checked_animation" /> -</animated-selector> +</animated-selector> diff --git a/core/res/res/drawable/ic_checkbox_checked.xml b/core/res/res/drawable/ic_checkbox_checked.xml index 476411516dad..cc7b5df6fac4 100644 --- a/core/res/res/drawable/ic_checkbox_checked.xml +++ b/core/res/res/drawable/ic_checkbox_checked.xml @@ -22,7 +22,7 @@ android:viewportWidth="48" android:height="32dp" android:viewportHeight="48" - android:tint="?attr/colorControlNormal" > + android:tint="?attr/colorControlActivated" > <group android:name="icon_null" android:translateX="24" diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 6fc1a45b7920..ad596db2277d 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Stel op"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Haal uit"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Verken"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Geen passende aktiwiteite gevind nie."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Roeteer media-uitvoer"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Laat \'n program toe om media-uitvoere na ander eksterne toestelle te roeteer."</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 6a3d0c26d484..827d662f6182 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"አዋቅር"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"አስወጣ"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"ያስሱ"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"ምንም ተመሳሳይ እንቅስቃሴዎች አልተገኙም።"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"የሚዲያ ውፅአት መንገድ"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"አንድ መተግበሪያ የሚዲያ ውፅአትን ወደ ሌላ ውጫዊ መሳሪያ እንዲመራ ይፈቅድለታል።"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index fc83bb6a5f73..9b3672a15dbc 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -1106,6 +1106,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"الإعداد"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"إلغاء"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"استكشاف"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"لم يتم العثور على أي أنشطة متطابقة."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"توجيه إخراج الوسائط"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"للسماح للتطبيق بتوجيه إخراج الوسائط إلى أجهزة خارجية أخرى."</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index d60e0f0477e9..a7a474211468 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Настройване"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Изваждане"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Изследване"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Не бяха намерени съответстващи дейности."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Насочване на изходящата мултимедия"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Разрешава на приложението да насочва изходящата мултимедия към други външни устройства."</string> diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml index d61965abd2e3..af2eb07f9e6d 100644 --- a/core/res/res/values-bn-rBD/strings.xml +++ b/core/res/res/values-bn-rBD/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"সেটআপ"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"বের করে নিন"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"ঘুরে দেখুন"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"কোনো সমরূপ কার্যকলাপ খুঁজে পাওয়া যায়নি৷"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"মিডিয়া আউটপুট রুট করুন"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"অ্যাপ্লিকেশানটিকে অন্যান্য বহিরাগত ডিভাইসে মিডিয়া আউটপুট রুট করার অনুমতি দেয়৷"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index d1eda0e082cd..394c5204ab36 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Configura"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Expulsa"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Explora"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"No s\'ha trobat cap activitat coincident."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Indicació de ruta de sortida de contingut multimèdia"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Permet que una aplicació indiqui la ruta de sortida de contingut multimèdia a altres dispositius externs."</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index ed5b413a65a5..90d0ba2061e7 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -1092,6 +1092,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Nastavení"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Odpojit"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Prozkoumat"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Nebyly nalezeny žádné odpovídající aktivity."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Směrování výstupu médií"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Umožňuje aplikaci směrovat výstup médií do dalších externích zařízení."</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 9918b089c116..7ec459f18f2e 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Konfigurer"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Skub ud"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Udforsk"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Der blev ikke fundet nogen matchende aktiviteter."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Viderefør medieoutput"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Tillader, at en applikation viderefører medieoutput til andre eksterne enheder."</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index cea19accd7a9..4bd91f236289 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Einrichten"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Auswerfen"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Entdecken"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Keine passenden Aktivitäten gefunden"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Medienausgabe umleiten"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Ermöglicht der App, die Medienausgabe auf andere externe Geräte umzuleiten."</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 0f9ada39f9de..836ed89e5b01 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Ρύθμιση"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Εξαγωγή"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Εξερεύνηση"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Δεν βρέθηκαν δραστηριότητες που να συμφωνούν με τα κριτήρια."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Διαγραφή διαδρομής δεδομένων εξόδου μέσων"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Επιτρέπει σε μια εφαρμογή τη διαγραφή διαδρομής δεδομένων εξόδου μέσων σε άλλες εξωτερικές συσκευές."</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index 4c7e534addda..031f1658d023 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Set up"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Eject"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Explore"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"No matching activities found."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Route media output"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Allows an application to route media output to other external devices."</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 4c7e534addda..031f1658d023 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Set up"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Eject"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Explore"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"No matching activities found."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Route media output"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Allows an application to route media output to other external devices."</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index 4c7e534addda..031f1658d023 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Set up"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Eject"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Explore"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"No matching activities found."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Route media output"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Allows an application to route media output to other external devices."</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 5a04b8b119a9..656abbf6df00 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Configuración"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Expulsar"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Explorar"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"No se encontraron actividades coincidentes."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Dirigir salida de medios"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Permite que la aplicación dirija salidas de medios a otros dispositivos externos."</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index f05757da82f8..fe8c67681c32 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Configurar"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Expulsar"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Explorar"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"No se ha encontrado ninguna actividad coincidente."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Dirigir salida de medio"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Permite que la aplicación dirija salidas de medios a otros dispositivos externos."</string> diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml index 9ee98df5b537..7259886e105a 100644 --- a/core/res/res/values-et-rEE/strings.xml +++ b/core/res/res/values-et-rEE/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Seadistamine"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Eemaldamine"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Avastamine"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Sobivat tegevust ei leitud"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Meediaväljundi teekonna koostamine"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Võimaldab rakendusel koostada teekonna meediaväljundist teistesse välistesse seadmetesse."</string> diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml index 31371d0b7e65..f12151c0b8b5 100644 --- a/core/res/res/values-eu-rES/strings.xml +++ b/core/res/res/values-eu-rES/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Konfigurazioa"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Atera"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Arakatu"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Ez da bat datorren jarduerarik aurkitu."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Multimedia-irteera bideratzea"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Multimedia elementuak kanpoko gailuetara bideratzeko baimena ematen die aplikazioei."</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 6e831f562b10..2808a787dee7 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"تنظیم"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"بیرون راندن"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"کاوش"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"فعالیتی مطابق با این مورد یافت نشد."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"تعیین مسیر خروجی رسانه"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"به یک برنامه اجازه میدهد خروجی رسانه را به دستگاههای خارجی دیگر تعیین مسیر کند."</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index cb0f601ffecb..1d71bd102b10 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Asennus"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Poista"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Tutustu"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Osuvia toimintoja ei löytynyt."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Median reititys"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Antaa sovelluksen reitittää mediaa muihin ulkoisiin laitteisiin."</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 9bed8505812f..2b81a1882de8 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Configuration"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Éjecter"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Découvrir"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Aucune activité correspondante trouvée."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Diriger la sortie multimédia"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Permet à une application de diriger la sortie multimédia vers d\'autres appareils externes."</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index b46f4d5fb142..55c4f5ddd6e7 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Configurer"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Éjecter"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Parcourir"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Aucune activité correspondante trouvée."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Diriger la sortie multimédia"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Permet à une application de diriger la sortie multimédia vers d\'autres appareils externes."</string> diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml index ca089bb09466..c2c67bcc69f6 100644 --- a/core/res/res/values-gl-rES/strings.xml +++ b/core/res/res/values-gl-rES/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Configuración"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Expulsar"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Explorar"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Non se atoparon actividades que coincidan."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Dirixir saída multimedia"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Permite a unha aplicación dirixir a saída multimedia a outros dispositivos externos."</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 9f90ed6c867c..5d954e212885 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"सेट करें"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"निकालें"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"एक्सप्लोर करें"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"कोई मिलती-जुलती गतिविधि नहीं मिली."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"मीडिया आउटपुट को रूट करें"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"ऐप्स को मीडिया आउटपुट को अन्य बाहरी डिवाइस पर रूट करने देता है."</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index a340ac60ecd4..cf81cd144611 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -1085,6 +1085,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Postavljanje"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Izbaci"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Istražite"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Nisu pronađene podudarne radnje."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Usmjeravanje medijskog izlaza"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Aplikaciji omogućuje usmjeravanje medijskog izlaza na druge vanjske uređaje."</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index f1db0a8653ed..ae606b280414 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Beállítás"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Kiadás"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Felfedezés"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Nincs megfelelő tevékenység."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Médiafájlok kimenetének irányítása"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Lehetővé teszi az alkalmazás számára, hogy más külső eszközökre irányítsa a médiafájlok lejátszását."</string> diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml index 380757804b61..f393c8794d97 100644 --- a/core/res/res/values-hy-rAM/strings.xml +++ b/core/res/res/values-hy-rAM/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Կարգավորում"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Անջատել"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Ուսումնասիրել"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Համընկնող գործունեություններ չգտնվեցին:"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Երթուղել մեդիա արտածումը"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Թույլ է տալիս հավելվածին մեդիա արտածումը երթուղել այլ արտաքին սարքեր:"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 59f48cc4b608..298f204178f8 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Siapkan"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Keluarkan"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Jelajahi"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Tidak ditemukan aktivitas yang sesuai."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Menentukan rute keluaran media"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Memungkinkan aplikasi menentukan rute keluaran media ke perangkat eksternal lainnya."</string> diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml index a234eb46fb6c..b36322b14858 100644 --- a/core/res/res/values-is-rIS/strings.xml +++ b/core/res/res/values-is-rIS/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Uppsetning"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Fjarlægja"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Kanna"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Engar aðgerðir með samsvörun fundust."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Beina margmiðlunarúttaki"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Leyfir forriti að beina margmiðlunarúttaki til annarra ytri tækja."</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index a3ae79d91a3c..5a2bf7abe1b7 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Configura"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Espelli"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Scopri"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Nessuna attività corrispondente trovata."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Indirizzamento uscita media"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Consente a un\'applicazione di indirizzare l\'uscita di media verso altri dispositivi esterni."</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 6031b04a2ecc..0f2a691a3a2a 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -1092,6 +1092,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"הגדר"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"הוצא"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"גלה"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"לא נמצאו פעילויות תואמות."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"ניתוב פלט מדיה"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"מאפשר לאפליקציה לנתב פלט מדיה למכשירים חיצוניים אחרים."</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 9c772578d299..71eec5634d0e 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"セットアップ"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"取り外し"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"外部メディア"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"一致するアクティビティが見つかりません。"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"メディア出力のルーティング"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"メディア出力を他の外部デバイスにルーティングすることをアプリに許可します。"</string> diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml index b270ee350d4f..1fc1b9593824 100644 --- a/core/res/res/values-ka-rGE/strings.xml +++ b/core/res/res/values-ka-rGE/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"დაყენება"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"გამოღება"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"დათვალიერება"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"შესატყვისი აქტივობები არ არის."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"მულტიმედია მონაცემების გადამისამართება"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"აპლიკაციას შეეძლება გადაამისამართოს მულტიმედია მონაცემები სხვა გარე მოწყობილობებისკენ."</string> diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml index fc88343769f4..5808e6db7519 100644 --- a/core/res/res/values-kk-rKZ/strings.xml +++ b/core/res/res/values-kk-rKZ/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Орнату"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Шығару"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Зерттеу"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Сәйкес әрекеттер табылмады."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Медиа шығысын бағыттау"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Қолданбаға медиа шығысын басқа сыртқы құрылғыларға бағыттау мүмкіндігін береді."</string> diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml index eeee275391d2..423506f88f8d 100644 --- a/core/res/res/values-km-rKH/strings.xml +++ b/core/res/res/values-km-rKH/strings.xml @@ -1080,6 +1080,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"ដំឡើង"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"ដកចេញ"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"រុករក"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"រកមិនឃើញសកម្មភាពផ្គូផ្គង។"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"នាំផ្លូវលទ្ធផលមេឌៀ"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"ឲ្យកម្មវិធីនាំផ្លូវលទ្ធផលមេឌៀទៅឧបករណ៍ខាងក្រៅផ្សេង។"</string> diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml index 125625f3f101..eca6ee8119a5 100644 --- a/core/res/res/values-kn-rIN/strings.xml +++ b/core/res/res/values-kn-rIN/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"ಸೆಟಪ್"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"ಎಜೆಕ್ಟ್ ಮಾಡು"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"ಎಕ್ಸ್ಪ್ಲೋರ್"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"ಯಾವುದೇ ಹೊಂದಾಣಿಕೆಯ ಚಟುವಟಿಕೆಗಳು ಕಂಡುಬಂದಿಲ್ಲ."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"ಮೀಡಿಯಾ ಔಟ್ಪುಟ್ ಅನ್ನು ರೂಟ್ ಮಾಡಿ"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"ಇತರ ಬಾಹ್ಯ ಸಾಧನಗಳಿಗೆ ಮೀಡಿಯಾ ಔಟ್ಪುಟ್ ಅನ್ನು ರೂಟ್ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 4687d1de982e..853a6edf6a52 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -274,10 +274,8 @@ <string name="permdesc_receiveWapPush" msgid="748232190220583385">"앱이 WAP 메시지를 수신하고 처리할 수 있도록 허용합니다. 이는 앱이 사용자에게 표시하지 않고 기기로 전송된 메시지를 모니터링 또는 삭제할 수도 있다는 것을 의미합니다."</string> <string name="permlab_getTasks" msgid="6466095396623933906">"실행 중인 앱 검색"</string> <string name="permdesc_getTasks" msgid="7454215995847658102">"앱이 현재 실행 중이거나 최근에 실행된 작업에 대한 정보를 검색할 수 있도록 허용합니다. 이 경우 앱이 기기에서 사용되는 다른 앱에 대한 정보를 검색할 수 있습니다."</string> - <!-- no translation found for permlab_manageProfileAndDeviceOwners (5979288447973722097) --> - <skip /> - <!-- no translation found for permdesc_manageProfileAndDeviceOwners (106894851498657169) --> - <skip /> + <string name="permlab_manageProfileAndDeviceOwners" msgid="5979288447973722097">"프로필 및 기기 소유자 관리"</string> + <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"앱이 프로필 소유자와 기기 소유자를 설정하도록 허용합니다."</string> <string name="permlab_reorderTasks" msgid="2018575526934422779">"실행 중인 앱 순서 재지정"</string> <string name="permdesc_reorderTasks" msgid="7734217754877439351">"앱이 사용자의 입력 없이 작업을 포그라운드나 백그라운드로 이동할 수 있도록 허용합니다."</string> <string name="permlab_enableCarMode" msgid="5684504058192921098">"운전모드 사용"</string> @@ -1080,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"설정"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"꺼내기"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"둘러보기"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"일치하는 활동이 없습니다."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"미디어 출력 연결"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"앱이 미디어 출력을 기타 외부 기기에 연결할 수 있도록 허용합니다."</string> diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml index 4fe2cfb6ef79..ee8766501721 100644 --- a/core/res/res/values-ky-rKG/strings.xml +++ b/core/res/res/values-ky-rKG/strings.xml @@ -1430,6 +1430,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Орнотуу"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Чыгаруу"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Изилдөө"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Туура келген аракеттер табылбады."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Медиа чыгарылышын багыттоо"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Колдонмого медиа мазмунду башка тышкы түзмөктөргө багыттоо уруксатын берет."</string> diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml index 0453de9653bf..5128827dd426 100644 --- a/core/res/res/values-lo-rLA/strings.xml +++ b/core/res/res/values-lo-rLA/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"ຕິດຕັ້ງ"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"ເອົາອອກ"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"ຄົ້ນຫາ"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"ບໍ່ພົບກິດຈະກຳທີ່ກົງກັນ."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"ກຳນົດເສັ້ນທາງເອົ້າພຸດຂອງສື່"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນ ກຳນົດເສັ້ນທາງເອົ້າພຸດຂອງສື່ໄປຫາອຸປະກອນພາຍນອກອື່ນໆ."</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 30c161094da0..ededc9a7d05c 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -1092,6 +1092,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Sąranka"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Pašalinti"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Naršyti"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Nerasta atitinkančios veiklos."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Medijos išvesties nukreipimas"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Leidžiama programai nukreipti medijos išvestį į kitus išorinius įrenginius."</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index bdefa646e0e0..9110e706ddec 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -1085,6 +1085,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Iestatīt"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Izstumt"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Izpētīt"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Nav atrasta neviena atbilstoša darbība."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Multivides datu izejas maršrutēšana"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Ļauj lietojumprogrammai maršrutēt multivides datu izeju uz citām ārējām ierīcēm."</string> diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml index 3ce3cf000e1c..4f5c913895d9 100644 --- a/core/res/res/values-mk-rMK/strings.xml +++ b/core/res/res/values-mk-rMK/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Поставување"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Извади"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Истражувај"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Не се пронајдени соодветни активности."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Насочи излез за медиуми"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Овозможува апликацијата да насочува излез за медиуми кон други надворешни уреди."</string> diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml index 0631b730c21f..62c5b1f93a70 100644 --- a/core/res/res/values-ml-rIN/strings.xml +++ b/core/res/res/values-ml-rIN/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"സജ്ജമാക്കുക"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"നിരസിക്കുക"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"പര്യവേക്ഷണം ചെയ്യുക"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"പൊരുത്തമുള്ള പ്രവർത്തനങ്ങളൊന്നും കണ്ടെത്തിയില്ല."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"മീഡിയ ഔട്ട്പുട്ട് റൂട്ടുചെയ്യുക"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"മീഡിയ ഔട്ട്പുട്ടിനെ മറ്റ് ബാഹ്യ ഉപകരണങ്ങളിലേക്ക് റൂട്ടുചെയ്യാൻ ഒരു അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string> diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml index 45576c11e314..971a6a8aa39e 100644 --- a/core/res/res/values-mn-rMN/strings.xml +++ b/core/res/res/values-mn-rMN/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Тохируулга"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Салгах"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Судлах"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Таарах активити олдсонгүй."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Медиа гаралтыг чиглүүлэх"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Аппликешн нь медиа гаралтыг бусад гадаад төхөөрөмжрүү чиглүүлэх боломжтой."</string> diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml index e52fe37a4dda..8bca6a515fbe 100644 --- a/core/res/res/values-mr-rIN/strings.xml +++ b/core/res/res/values-mr-rIN/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"सेटअप"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"बाहेर काढा"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"एक्सप्लोर करा"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"कोणतेही जुळणारे क्रियाकलाप आढळले नाहीत."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"मीडिया आउटपुट मार्गस्थ करा"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"अन्य बाह्य डिव्हाइसेसवरील रूट मीडिया आउटपुट वर अनुप्रयोगास अनुमती देते."</string> diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml index 7d3a3145b440..f068fcdf34c8 100644 --- a/core/res/res/values-ms-rMY/strings.xml +++ b/core/res/res/values-ms-rMY/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Persediaan"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Tanggalkan"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Teroka"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Tiada aktiviti yang sepadan ditemui."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Buat laluan output media"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Membenarkan apl untuk membuat laluan output media ke peranti luaran lain."</string> diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml index ffcf6b80c6c0..e315f56ce752 100644 --- a/core/res/res/values-my-rMM/strings.xml +++ b/core/res/res/values-my-rMM/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"စဖွင့်သတ်မှတ်ရန်"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"ထုတ်မည်"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"စူးစမ်းရန်"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"တိုက်ဆိုင်သော ပြုလုပ်ချက် ရှာမတွေ့ပါ"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"မီဒီယာထွက်ပေါက်အား လမ်းလွှဲပြောင်းခြင်း"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"အပလီကေးရှင်းအား မီဒီယာ ထုတ်လွှတ်မှုကို အခြားပြင်ပ စက်ပစ္စည်းများသို့ လွှဲပြောင်းခွင့်ပြုပါ"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 47ff2a014d33..9f0f3b6a4b06 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Konfigurering"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Løs ut"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Utforsk"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Finner ingen samsvarende aktiviteter."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Videresending av medieutdata"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Lar en app videresende medieutdata til andre eksterne enheter."</string> diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml index 7591e80e51c3..66f8ae2f53e2 100644 --- a/core/res/res/values-ne-rNP/strings.xml +++ b/core/res/res/values-ne-rNP/strings.xml @@ -1074,11 +1074,11 @@ <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"तयारी गर्दै <xliff:g id="NAME">%s</xliff:g>"</string> <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"त्रुटिहरूको लागि जाँच गर्दै"</string> <string name="ext_media_new_notification_message" msgid="7589986898808506239">"नयाँ <xliff:g id="NAME">%s</xliff:g> भेटियो"</string> - <string name="ext_media_ready_notification_message" msgid="4083398150380114462">"फोटोहरू र मिडिया स्थानान्तरणका लागि"</string> + <string name="ext_media_ready_notification_message" msgid="4083398150380114462">"तस्बिरहरू र मिडिया स्थानान्तरणका लागि"</string> <string name="ext_media_unmountable_notification_title" msgid="4863279349863279603">"<xliff:g id="NAME">%s</xliff:g> बिग्रेको छ।"</string> - <string name="ext_media_unmountable_notification_message" msgid="7391672496565685690">"<xliff:g id="NAME">%s</xliff:g> बिग्रेको छ; यसलाई पुनः फर्म्याट गर्न प्रयास गर्नुहोस्"</string> + <string name="ext_media_unmountable_notification_message" msgid="7391672496565685690">"<xliff:g id="NAME">%s</xliff:g> बिग्रेको छ; यसलाई पुनः ढाँचा गर्न प्रयास गर्नुहोस्"</string> <string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> अप्रत्याशित रूपमा निकालियो"</string> - <string name="ext_media_badremoval_notification_message" msgid="380176703346946313">"डेटा नोक्सानबाट बच्न निकाल्नु अघि <xliff:g id="NAME">%s</xliff:g> अनमाउन्ट गर्नुहोस्"</string> + <string name="ext_media_badremoval_notification_message" msgid="380176703346946313">"डेटा हराउनबाट जोगाउन निकाल्नु अघि <xliff:g id="NAME">%s</xliff:g> अनमाउन्ट गर्नुहोस्"</string> <string name="ext_media_nomedia_notification_title" msgid="1704840188641749091">"निकालियो <xliff:g id="NAME">%s</xliff:g>"</string> <string name="ext_media_nomedia_notification_message" msgid="6471542972147056586">"<xliff:g id="NAME">%s</xliff:g> निकालियो; नयाँ हाल्नुहोस्"</string> <string name="ext_media_unmounting_notification_title" msgid="640674168454809372">"अझै निकाल्दै <xliff:g id="NAME">%s</xliff:g>..."</string> @@ -1086,6 +1086,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"सेटअप"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"निकाल्नुहोस्"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"अन्वेषण गर्नुहोस्"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"कुनै मिल्ने गतिविधि पाइएन।"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"मिडिया परिणाम दिशानिर्देश गर्नुहोस्"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"मिडिया परिणामलाई अन्य बाहिरी उपकरणहरूसँग लैजानको लागि अनुप्रयोगलाई अनुमति दिन्छ।"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index f5d5e8e0c335..7391d4b5746b 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Configuratie"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Uitwerpen"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Verkennen"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Geen overeenkomende activiteiten gevonden."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Media-uitvoer aansturen"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Hiermee kan een app media-uitvoer naar andere externe apparaten doorsturen."</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index e4aca19f437b..d87fd22eba23 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -1092,6 +1092,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Skonfiguruj"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Wysuń"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Przeglądaj"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Nie znaleziono pasujących działań."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Kierowanie wyjścia multimediów"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Pozwala aplikacji na kierowanie wyjściowych danych multimedialnych do innych urządzeń zewnętrznych."</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index e75620bc6d7d..28c14da20327 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Configuração"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Ejetar"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Explorar"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Não foi encontrada nenhuma atividade correspondente."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Encaminhar saída de som multimédia"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Permite que a aplicação encaminhe a saída de som multimédia para outros dispositivos externos."</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index f2c85275372b..b1551b08a308 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Configurar"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Ejetar"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Explorar"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Nenhum atividade correspondente foi encontrada."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Rotear saída de mídia"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Permite que um app faça o roteamento de saída de mídia para outros dispositivos externos."</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index df7e7786d0f7..1790122614c1 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -1085,6 +1085,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Configurați"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Scoateți"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Explorați"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Nu s-a găsit nicio activitate potrivită."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Direcţionează rezultatele media"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Permite unei aplicații să direcţioneze rezultate media către alte dispozitive externe."</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 8b6d913039de..b9eab5784fb3 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -1092,6 +1092,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Настроить"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Извлечь"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Обзор"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Подходящих действий не найдено."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Перенаправление мультимедийных данных"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Приложение сможет направлять поток мультимедиа на другие внешние устройства."</string> diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml index 56e157629bb6..f21d99e54700 100644 --- a/core/res/res/values-si-rLK/strings.xml +++ b/core/res/res/values-si-rLK/strings.xml @@ -1080,6 +1080,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"ස්ථාපනය"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"ගැලවීම"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"ගවේෂණය කරන්න"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"ගැලපෙන ක්රියාකාරකම් හමු නොවුණි."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"මාධ්ය ප්රතිදානයේ මාර්ගගත කිරීම"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"වෙනත් බාහිර උපාංග වෙත මාධ්ය ප්රතිදානය යැවීමට යෙදුමට අවසර දෙන්න."</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index 498dcdec2375..8e97275a6b18 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -1092,6 +1092,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Nastavenie"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Odpojiť"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Preskúmať"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Nenašli sa žiadne zodpovedajúce aktivity."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Smerovanie výstupu médií"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Umožňuje aplikácii smerovať výstup médií do ďalších externých zariadení."</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 77f9a1ff5b4e..0ed81d3d02c7 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -1092,6 +1092,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Nastavitev"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Izvrzite"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Raziščite"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Ni ustreznih dejavnosti."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Preusmeritev predstavnosti"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Aplikaciji omogoča preusmerjanje predstavnosti v druge zunanje naprave."</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index e3e6f1ddc597..c18d98fd0b54 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -1085,6 +1085,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Подешавање"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Избаци"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Истражи"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Није пронађена ниједна подударна активност."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Усмеравање излаза медија"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Дозвољава апликацији да усмерава излаз медија на друге спољне уређаје."</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index b78e63298715..69817172dff9 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Konfiguration"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Mata ut"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Utforska"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Det gick inte att hitta några matchande aktiviteter."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Omdirigera medieuppspelning"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Tillåter att appen omdirigerar medieuppspelningar till andra externa enheter."</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 8c58d5b23552..e807ca134c23 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Sanidi"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Ondoa"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Chunguza"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Hakuna shughuli zinazolingana zilizopatikana."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Fuatalia utoaji wa habari"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Inaruhusu programu kufuatilia utoaji wa habari kwa vifaa vingine vya nje."</string> diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml index a33af512b383..f07fcacd9d3f 100644 --- a/core/res/res/values-ta-rIN/strings.xml +++ b/core/res/res/values-ta-rIN/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"அமைவு"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"வெளியேற்று"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"உலாவுக"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"பொருந்தும் செயல்பாடுகள் கண்டறியப்படவில்லை."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"மீடியா அவுட்புட்டை வழிசெலுத்துதல்"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"மீடியாவைப் பிற வெளிப்புறச் சாதனங்களுக்கு வெளியீடாக வழிகாட்ட பயன்பாட்டை அனுமதிக்கிறது."</string> diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml index 6bd400726555..a36c8feed14c 100644 --- a/core/res/res/values-te-rIN/strings.xml +++ b/core/res/res/values-te-rIN/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"సెటప్ చేయి"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"తొలగించు"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"విశ్లేషించు"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"సరిపోలే కార్యాచరణలు కనుగొనబడలేదు."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"ప్రసార మాధ్యమ అవుట్పుట్ను మళ్లించడం"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"మీడియా అవుట్పుట్ను ఇతర బాహ్య పరికరాలకు మళ్లించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 501ce0add56d..84d31a317af7 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"ตั้งค่า"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"นำอุปกรณ์ออก"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"สำรวจ"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"ไม่พบกิจกรรมที่ตรงกัน"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"กำหนดเส้นทางเอาต์พุตของสื่อ"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"อนุญาตให้แอปพลิเคชันกำหนดเส้นทางเอาต์พุตของสื่อไปยังอุปกรณ์ภายนอกอื่นๆ"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 545bcd5cc1f5..e3434046cc90 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"I-setup"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"I-eject"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"I-explore"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Walang nahanap na mga tumutugmang aktibidad."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"I-route ang output ng media"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Pinapayagan ang application na mag-route ng output ng media sa iba pang mga panlabas na device."</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index fa2405e4f96b..c9166cda43fa 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -274,10 +274,8 @@ <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Uygulamaya WAP mesajlarını alma ve işleme izni verir. Buna, size gönderilen mesajları takip edip size göstermeden silebilme izni de dahildir."</string> <string name="permlab_getTasks" msgid="6466095396623933906">"çalışan uygulamaları al"</string> <string name="permdesc_getTasks" msgid="7454215995847658102">"Uygulamaya o anda ve son çalışan görevler hakkında bilgi alma izni verir. Bu izin, uygulamanın cihaz tarafından kullanılan uygulamalar hakkında bilgi elde etmesine olanak sağlayabilir."</string> - <!-- no translation found for permlab_manageProfileAndDeviceOwners (5979288447973722097) --> - <skip /> - <!-- no translation found for permdesc_manageProfileAndDeviceOwners (106894851498657169) --> - <skip /> + <string name="permlab_manageProfileAndDeviceOwners" msgid="5979288447973722097">"Profil ve cihaz sahiplerini yönetme"</string> + <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"Uygulamaların, profil sahiplerini ve cihaz sahibini ayarlamasına izin verir."</string> <string name="permlab_reorderTasks" msgid="2018575526934422779">"çalışan uygulamaları yeniden sırala"</string> <string name="permdesc_reorderTasks" msgid="7734217754877439351">"Uygulamaya, görevleri ön plana ve arka plana taşıma izni verir. Uygulama bunu sizden bir giriş olmadan yapabilir."</string> <string name="permlab_enableCarMode" msgid="5684504058192921098">"araç modunu etkinleştir"</string> @@ -1080,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Kurulum"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Çıkar"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Keşfedin"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Eşleşen hiçbir etkinlik bulunamadı."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Medya çıktısını yönlendir"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Uygulamaya medya çıktısını başka harici cihazlara yönlendirme izni verir."</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index 527f09a3192c..81c24a4cf8aa 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -1092,6 +1092,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Налаштувати"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Відключити"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Переглянути"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Відповідні дії не знайдено."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Скеровувати вивід медіа-даних"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Дозволяє програмі скеровувати вивід медіа-даних на інші зовнішні пристрої."</string> diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml index a9d757267ab4..03ad6ac280ac 100644 --- a/core/res/res/values-ur-rPK/strings.xml +++ b/core/res/res/values-ur-rPK/strings.xml @@ -274,10 +274,8 @@ <string name="permdesc_receiveWapPush" msgid="748232190220583385">"ایپ کو WAP پیغامات حاصل اور ان پر کارروائی کرنے کی اجازت دیتا ہے۔ اس اجازت میں آپ کو مرسلہ پیغامات آپ کو دکھائے بغیر ان پر نگاہ رکھنے یا انہیں حذف کرنے کی اہلیت شامل ہے۔"</string> <string name="permlab_getTasks" msgid="6466095396623933906">"چل رہی ایپس کی بازیافت کریں"</string> <string name="permdesc_getTasks" msgid="7454215995847658102">"ایپ کو موجودہ اور حالیہ چل رہے ٹاسکس کے بارے میں معلومات بازیافت کرنے کی اجازت دیتا ہے۔ یہ ایپ کو اس بارے میں معلومات دریافت کرنے کی اجازت دے سکتا ہے کہ آلہ پر کون سی ایپلیکیشنز استعمال کی جاتی ہیں۔"</string> - <!-- no translation found for permlab_manageProfileAndDeviceOwners (5979288447973722097) --> - <skip /> - <!-- no translation found for permdesc_manageProfileAndDeviceOwners (106894851498657169) --> - <skip /> + <string name="permlab_manageProfileAndDeviceOwners" msgid="5979288447973722097">"پروفائل اور آلہ کے مالکان کا نظم کریں"</string> + <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"ایپس کو پروفائل کے مالکان اور آلہ کے مالک کو سیٹ کرنے کی اجازت دیتا ہے۔"</string> <string name="permlab_reorderTasks" msgid="2018575526934422779">"چل رہی ایپس کو دوبارہ ترتیب دیں"</string> <string name="permdesc_reorderTasks" msgid="7734217754877439351">"ایپ کو پیش منظر یا پس منظر میں ٹاسکس کو منتقل کرنے کی اجازت دیتا ہے۔ ایپ آپ کے ان پٹ کے بغیر یہ کام کرسکتی ہے۔"</string> <string name="permlab_enableCarMode" msgid="5684504058192921098">"کار وضع فعال کریں"</string> @@ -1080,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"ترتیب دیں"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"خارج کریں"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"دریافت کریں"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"کوئی مماثل سرگرمیاں نہیں ملیں۔"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"میڈیا آؤٹ پٹ کی سمت طے کریں"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"کسی ایپلیکیشن کو دوسرے خارجی آلات تک میڈیا آؤٹ پٹ کا راستہ بنانے کی اجازت دیتا ہے۔"</string> diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml index ec1a840007ba..9706535e4012 100644 --- a/core/res/res/values-uz-rUZ/strings.xml +++ b/core/res/res/values-uz-rUZ/strings.xml @@ -275,7 +275,7 @@ <string name="permlab_getTasks" msgid="6466095396623933906">"ishlab turgan ilovalar to‘g‘risida ma’lumot olish"</string> <string name="permdesc_getTasks" msgid="7454215995847658102">"Ilovaga hozirda va so‘nggi ishga tushirilgan vazifalar haqida to‘liq ma’lumot olishiga ruxsat beradi. Bu ilovaga qurilmadagi ishlatilayotgan ilovalar haqidagi ma’lumotlarga ega bo‘lishiga ruxsat berishi mumkin."</string> <string name="permlab_manageProfileAndDeviceOwners" msgid="5979288447973722097">"Profil va qurilma egalarini boshqarish"</string> - <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"Ilovaga profil va qurilma egalarini sozlash uchun ruxsat beradi"</string> + <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"Ilovaga profil egalari va qurilma egalarini aniqlash uchun ruxsat beradi."</string> <string name="permlab_reorderTasks" msgid="2018575526934422779">"ishlab turgan ilovalarni qayta tartiblash"</string> <string name="permdesc_reorderTasks" msgid="7734217754877439351">"Ilovalarga vazifalarni old va orqa fonga o‘tkazish uchun ruxsat beradi. Ilova buni sizning yordamingizsiz bajarishi mumkin."</string> <string name="permlab_enableCarMode" msgid="5684504058192921098">"mashina usulini yoqish"</string> @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Sozlash"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Chiqarish"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"O‘rganish"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Hech qanday mos faoliyat topilmadi."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Media chiqishni yo‘naltirish"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Ilovaga media chiqish ovozini boshqa tashqi qurilmalarga yo‘naltirish uchun ruxsat beradi."</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index d84f2fe20fe5..a1509af633c6 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -274,10 +274,8 @@ <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Cho phép ứng dụng nhận và xử lý tin nhắn WAP. Quyền này bao gồm khả năng giám sát hoặc xóa tin nhắn được gửi cho bạn mà không hiển thị chúng cho bạn."</string> <string name="permlab_getTasks" msgid="6466095396623933906">"truy xuất các ứng dụng đang chạy"</string> <string name="permdesc_getTasks" msgid="7454215995847658102">"Cho phép ứng dụng truy xuất thông tin về các công việc đã và đang chạy gần đây. Việc này có thể cho phép ứng dụng phát hiện thông tin về những ứng dụng nào đã được sử dụng trên thiết bị."</string> - <!-- no translation found for permlab_manageProfileAndDeviceOwners (5979288447973722097) --> - <skip /> - <!-- no translation found for permdesc_manageProfileAndDeviceOwners (106894851498657169) --> - <skip /> + <string name="permlab_manageProfileAndDeviceOwners" msgid="5979288447973722097">"Quản lý chủ sở hữu thiết bị và hồ sơ"</string> + <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"Cho phép ứng dụng đặt chủ sở hữu hồ sơ và chủ sở hữu thiết bị."</string> <string name="permlab_reorderTasks" msgid="2018575526934422779">"sắp xếp lại những ứng dụng đang chạy"</string> <string name="permdesc_reorderTasks" msgid="7734217754877439351">"Cho phép ứng dụng di chuyển công việc sang nền trước và nền sau. Ứng dụng có thể thực hiện việc này mà không cần bạn nhập."</string> <string name="permlab_enableCarMode" msgid="5684504058192921098">"bật chế độ trên ô tô"</string> @@ -1080,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Thiết lập"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Tháo"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Khám phá"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Không tìm thấy hoạt động nào phù hợp."</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Định tuyến thiết bị ra phương tiện"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Cho phép ứng dụng định tuyến thiết bị ra phương tiện đến các thiết bị bên ngoài khác."</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 3e17ef4dff74..bbe328747918 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -274,10 +274,8 @@ <string name="permdesc_receiveWapPush" msgid="748232190220583385">"允许该应用接收和处理 WAP 消息。此权限包括监视发送给您的消息或删除发送给您的消息而不向您显示的功能。"</string> <string name="permlab_getTasks" msgid="6466095396623933906">"检索正在运行的应用"</string> <string name="permdesc_getTasks" msgid="7454215995847658102">"允许该应用检索近期运行的和当前正在运行的任务的相关信息。此权限可让该应用了解设备上使用了哪些应用。"</string> - <!-- no translation found for permlab_manageProfileAndDeviceOwners (5979288447973722097) --> - <skip /> - <!-- no translation found for permdesc_manageProfileAndDeviceOwners (106894851498657169) --> - <skip /> + <string name="permlab_manageProfileAndDeviceOwners" msgid="5979288447973722097">"管理个人资料和设备所有者"</string> + <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"允许应用设置个人资料所有者和设备所有者。"</string> <string name="permlab_reorderTasks" msgid="2018575526934422779">"对正在运行的应用重新排序"</string> <string name="permdesc_reorderTasks" msgid="7734217754877439351">"允许该应用将任务移动到前台和后台。该应用可能不经您的命令自行执行此操作。"</string> <string name="permlab_enableCarMode" msgid="5684504058192921098">"启用车载模式"</string> @@ -1080,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"设置"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"弹出"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"浏览"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"未找到匹配的活动。"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"更改媒体输出线路"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"允许该应用将媒体输出线路更改到其他外部设备。"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 865baa3de3f1..a6988483af49 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -274,10 +274,8 @@ <string name="permdesc_receiveWapPush" msgid="748232190220583385">"允許應用程式接收和處理 WAP 訊息。這項權限也能讓應用程式監控訊息,或在您閱讀訊息前擅自刪除訊息。"</string> <string name="permlab_getTasks" msgid="6466095396623933906">"擷取執行中的應用程式"</string> <string name="permdesc_getTasks" msgid="7454215995847658102">"允許應用程式擷取有關目前和最近執行的工作的資訊。如此一來,應用程式或可找出裝置上所使用應用程式的相關資訊。"</string> - <!-- no translation found for permlab_manageProfileAndDeviceOwners (5979288447973722097) --> - <skip /> - <!-- no translation found for permdesc_manageProfileAndDeviceOwners (106894851498657169) --> - <skip /> + <string name="permlab_manageProfileAndDeviceOwners" msgid="5979288447973722097">"管理您的設定檔和裝置擁有者"</string> + <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"允許應用程式設定檔案擁有者和裝置擁有者。"</string> <string name="permlab_reorderTasks" msgid="2018575526934422779">"為執行中的應用程式重新排序"</string> <string name="permdesc_reorderTasks" msgid="7734217754877439351">"允許應用程式將工作移至前景或背景。應用程式可以自行處理,您無須操作。"</string> <string name="permlab_enableCarMode" msgid="5684504058192921098">"啟用行車模式"</string> @@ -1080,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"設定"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"移除"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"探索"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"找不到相符的活動。"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"轉送媒體輸出"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"允許應用程式將媒體輸出轉送至其他外部裝置。"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index f61d42e0f18d..009117af90d2 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -274,10 +274,8 @@ <string name="permdesc_receiveWapPush" msgid="748232190220583385">"允許應用程式接收和處理 WAP 訊息。這項權限也能讓應用程式監控訊息,或在您閱讀訊息前擅自刪除訊息。"</string> <string name="permlab_getTasks" msgid="6466095396623933906">"擷取執行中的應用程式"</string> <string name="permdesc_getTasks" msgid="7454215995847658102">"允許應用程式擷取最近執行工作的資訊。這項設定可讓應用程式找出裝置所用程式的相關資訊。"</string> - <!-- no translation found for permlab_manageProfileAndDeviceOwners (5979288447973722097) --> - <skip /> - <!-- no translation found for permdesc_manageProfileAndDeviceOwners (106894851498657169) --> - <skip /> + <string name="permlab_manageProfileAndDeviceOwners" msgid="5979288447973722097">"管理個人資料和裝置擁有者"</string> + <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"允許應用程式設定個人資料擁有者和裝置擁有者。"</string> <string name="permlab_reorderTasks" msgid="2018575526934422779">"重新排序正在執行的應用程式"</string> <string name="permdesc_reorderTasks" msgid="7734217754877439351">"允許應用程式將工作移至前景或背景。應用程式可以自行處理,不待您操作。"</string> <string name="permlab_enableCarMode" msgid="5684504058192921098">"啟用行車模式"</string> @@ -1080,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"設定"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"退出"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"探索"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"找不到相符的活動。"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"轉送媒體輸出"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"允許應用程式將媒體輸出轉送至其他外部裝置。"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 8c2ec6e31599..a719e07d8202 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -1078,6 +1078,22 @@ <string name="ext_media_init_action" msgid="8317198948634872507">"Ukusetha"</string> <string name="ext_media_unmount_action" msgid="1121883233103278199">"Khipha"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"Hlola"</string> + <!-- no translation found for ext_media_missing_title (620980315821543904) --> + <skip /> + <!-- no translation found for ext_media_missing_message (5761133583368750174) --> + <skip /> + <!-- no translation found for ext_media_move_specific_title (1471100343872375842) --> + <skip /> + <!-- no translation found for ext_media_move_title (1022809140035962662) --> + <skip /> + <!-- no translation found for ext_media_move_success_title (8575300932957954671) --> + <skip /> + <!-- no translation found for ext_media_move_success_message (4199002148206265426) --> + <skip /> + <!-- no translation found for ext_media_move_failure_title (7613189040358789908) --> + <skip /> + <!-- no translation found for ext_media_move_failure_message (1978096440816403360) --> + <skip /> <string name="activity_list_empty" msgid="1675388330786841066">"Ayikho imisebenzi efanayo etholakele"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"Yenza umzila wemidiya wokukhiphayo"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"Ivumela uhlelo lokusebenza ukwenza umzila wokukhiphayo wemidiya kuya kumadivayisi angaphandle."</string> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 0c685e004bae..4631427cac31 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1044,7 +1044,8 @@ <p>NOTE: The value of {@link android.R.attr#screenOrientation} will be ignored for resizeable activities as the system doesn't support fixed orientation on a resizeable - activity. --> + activity. + @hide --> <attr name="resizeableActivity" format="boolean" /> <!-- This value indicates how tasks rooted at this activity will behave in lockTask mode. @@ -1796,6 +1797,7 @@ <attr name="autoRemoveFromRecents" /> <attr name="relinquishTaskIdentity" /> <attr name="resumeWhilePausing" /> + <!-- @hide --> <attr name="resizeableActivity" /> <attr name="lockTaskMode" /> <attr name="showForAllUsers" /> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 4609c791f13d..dd4c134cde42 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2610,7 +2610,6 @@ <public type="attr" name="trackTint" /> <public type="attr" name="trackTintMode" /> - <public type="attr" name="resizeableActivity" /> <public type="attr" name="start" /> <public type="attr" name="end" /> <public type="attr" name="windowLightStatusBar" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 51c2062d806e..3146f4158eeb 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3012,6 +3012,26 @@ <!-- Notification action to browse external media [CHAR LIMIT=20] --> <string name="ext_media_browse_action">Explore</string> + <!-- Notification title when external media is missing [CHAR LIMIT=30] --> + <string name="ext_media_missing_title"><xliff:g id="name" example="SD card">%s</xliff:g> missing</string> + <!-- Notification body when external media is missing [CHAR LIMIT=30] --> + <string name="ext_media_missing_message">Reinsert this device</string> + + <!-- Notification title when moving an application to external storage [CHAR LIMIT=30] --> + <string name="ext_media_move_specific_title">Moving <xliff:g id="name" example="Calculator">%s</xliff:g></string> + <!-- Notification title when moving data to external storage [CHAR LIMIT=32] --> + <string name="ext_media_move_title">Moving data</string> + + <!-- Notification title when moving data to external storage [CHAR LIMIT=32] --> + <string name="ext_media_move_success_title">Move complete</string> + <!-- Notification title when moving data to external storage [CHAR LIMIT=64] --> + <string name="ext_media_move_success_message">Data moved to <xliff:g id="name" example="SD card">%s</xliff:g></string> + + <!-- Notification title when moving data to external storage failed [CHAR LIMIT=32] --> + <string name="ext_media_move_failure_title">Couldn\'t move data</string> + <!-- Notification title when moving data to external storage failed [CHAR LIMIT=64] --> + <string name="ext_media_move_failure_message">Data left at original location</string> + <!-- Shown in LauncherActivity when the requested target Intent didn't return any matching Activities, leaving the list empty. --> <string name="activity_list_empty">No matching activities found.</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index b05fe075b95c..90437b9cd85d 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1899,6 +1899,14 @@ <java-symbol type="string" name="ext_media_init_action" /> <java-symbol type="string" name="ext_media_unmount_action" /> <java-symbol type="string" name="ext_media_browse_action" /> + <java-symbol type="string" name="ext_media_missing_title" /> + <java-symbol type="string" name="ext_media_missing_message" /> + <java-symbol type="string" name="ext_media_move_specific_title" /> + <java-symbol type="string" name="ext_media_move_title" /> + <java-symbol type="string" name="ext_media_move_success_title" /> + <java-symbol type="string" name="ext_media_move_success_message" /> + <java-symbol type="string" name="ext_media_move_failure_title" /> + <java-symbol type="string" name="ext_media_move_failure_message" /> <java-symbol type="string" name="usb_storage_error_message" /> <java-symbol type="string" name="usb_storage_message" /> <java-symbol type="string" name="usb_storage_notification_message" /> diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml index 0744feddd80b..e679e0a7fd83 100644 --- a/core/res/res/values/themes_material.xml +++ b/core/res/res/values/themes_material.xml @@ -56,11 +56,11 @@ please see themes_device_defaults.xml. <item name="textColorPrimary">@color/primary_text_material_dark</item> <item name="textColorPrimaryInverse">@color/primary_text_material_light</item> - <item name="textColorPrimaryActivated">@color/primary_text_activated_material_dark</item> + <item name="textColorPrimaryActivated">@color/primary_text_inverse_when_activated_material</item> <item name="textColorPrimaryDisableOnly">@color/primary_text_disable_only_material_dark</item> <item name="textColorSecondary">@color/secondary_text_material_dark</item> <item name="textColorSecondaryInverse">@color/secondary_text_material_light</item> - <item name="textColorSecondaryActivated">@color/secondary_text_activated_material_dark</item> + <item name="textColorSecondaryActivated">@color/secondary_text_inverse_when_activated_material</item> <item name="textColorTertiary">@color/secondary_text_material_dark</item> <item name="textColorTertiaryInverse">@color/secondary_text_material_light</item> <item name="textColorHint">@color/hint_foreground_material_dark</item> @@ -410,10 +410,10 @@ please see themes_device_defaults.xml. <item name="textColorPrimary">@color/primary_text_material_light</item> <item name="textColorPrimaryInverse">@color/primary_text_material_dark</item> - <item name="textColorPrimaryActivated">@color/primary_text_activated_material_light</item> + <item name="textColorPrimaryActivated">@color/primary_text_inverse_when_activated_material</item> <item name="textColorSecondary">@color/secondary_text_material_light</item> <item name="textColorSecondaryInverse">@color/secondary_text_material_dark</item> - <item name="textColorSecondaryActivated">@color/secondary_text_activated_material_light</item> + <item name="textColorSecondaryActivated">@color/secondary_text_inverse_when_activated_material</item> <item name="textColorTertiary">@color/secondary_text_material_light</item> <item name="textColorTertiaryInverse">@color/secondary_text_material_dark</item> <item name="textColorPrimaryDisableOnly">@color/primary_text_disable_only_material_light</item> @@ -777,10 +777,8 @@ please see themes_device_defaults.xml. <item name="textColorPrimary">@color/primary_text_material_light</item> <item name="textColorPrimaryInverse">@color/primary_text_material_dark</item> - <item name="textColorPrimaryActivated">@color/primary_text_activated_material_light</item> <item name="textColorSecondary">@color/secondary_text_material_light</item> <item name="textColorSecondaryInverse">@color/secondary_text_material_dark</item> - <item name="textColorSecondaryActivated">@color/secondary_text_activated_material_light</item> <item name="textColorTertiary">@color/secondary_text_material_light</item> <item name="textColorTertiaryInverse">@color/secondary_text_material_dark</item> <item name="textColorPrimaryDisableOnly">@color/primary_text_disable_only_material_light</item> @@ -814,11 +812,9 @@ please see themes_device_defaults.xml. <item name="textColorPrimary">@color/primary_text_material_dark</item> <item name="textColorPrimaryInverse">@color/primary_text_material_light</item> - <item name="textColorPrimaryActivated">@color/primary_text_activated_material_dark</item> <item name="textColorPrimaryDisableOnly">@color/primary_text_disable_only_material_dark</item> <item name="textColorSecondary">@color/secondary_text_material_dark</item> <item name="textColorSecondaryInverse">@color/secondary_text_material_light</item> - <item name="textColorSecondaryActivated">@color/secondary_text_activated_material_dark</item> <item name="textColorTertiary">@color/secondary_text_material_dark</item> <item name="textColorTertiaryInverse">@color/secondary_text_material_light</item> <item name="textColorHint">@color/hint_foreground_material_dark</item> diff --git a/docs/html-intl/intl/es/index.jd b/docs/html-intl/intl/es/index.jd new file mode 100644 index 000000000000..3c63b116de3a --- /dev/null +++ b/docs/html-intl/intl/es/index.jd @@ -0,0 +1,93 @@ +fullpage=true +page.viewport_width=970 +excludeFromSuggestions=true +page.metaDescription=El sitio oficial para los desarrolladores de Android. Proporciona el SDK de Android y la documentación para los diseñadores y desarrolladores de aplicaciones. +page.customHeadTag=<meta name="google-site-verification" content="sa-bIAI6GKvct3f61-WpRguHq-aNjtF7xJjMTSi79as" /> + +@jd:body + +<div class="home-new-carousel-1"> + <div class="fullscreen-carousel-content"> + <div class="vcenter"> + <div class="wrap clearfix"> + + <div class="static resource-flow-layout wrap col-16"> + <div class="resource resource-card resource-card-18x6"> + + <div class="landing-section-header"> + <div class="col-10"><img src="{@docRoot}images/home/l-hero_2x.png" srcset="{@docRoot}images/home/l-hero.png 1x, {@docRoot}images/home/l-hero_2x.png 2x" width="510" style="margin:20px 30px 0 30px"></div> + <div class="col-5" style=" margin-top:70px "> + <h3 stye="font-weight:300;">Android 5.0 Lollipop</h3> + <p>La actualización 5.0 de Android agrega una variedad de nuevas características para sus aplicaciones, como notificaciones en la pantalla de bloqueo, una nueva API de cámara, OpenGL ES 3.1, una nueva interfaz llamada "Material design", y mucho más.</p> + <a href="{@docRoot}about/versions/lollipop.html" class="landing-button landing-primary">Más información</a> + </div> + </div> + </div> + </div> + <h2> </h2> + <div style="margin-top:20px;height:115px" class="resource-widget resource-flow-layout wrap col-16 + no-section" data-query="collection:index/primary" data-resourcestyle="card" + data-sortorder="-timestamp" data-maxresults="3" data-cardsizes="6x2,6x2,6x2"></div> <!-- end .resource-widget --> + </div> <!-- end .wrap --> + </div> <!-- end .vcenter --> + </div> <!-- end .fullscreen-carousel-content --> +</div> <!-- end .fullscreen-carousel --> + +<div class="actions-bar" style="margin-top:20px"> + <div class="wrap"> + <div class="actions"> + <div><a href="{@docRoot}sdk/index.html">Obtener el SDK</a></div> + <div><a href="{@docRoot}samples/index.html">Examinar muestras</a></div> + <div><a href="//www.youtube.com/user/androiddevelopers">Mirar videos</a></div> + <div><a href="{@docRoot}distribute/googleplay/developer-console.html">Administrar tus aplicaciones</a></div> + </div><!-- end .actions --> + </div><!-- end .wrap --> +</div><!-- end .actions-bar --> + + + +<div class="landing-rest-of-page"> + <div class="landing-section"> + <div class="wrap"> + <div class="landing-section-header"> + + <div class="landing-h1" style="margin-top:0px">Creado para un mundo de múltiples pantallas</div> + <div class="landing-subhead" style="margin-top: 20px;"> + Android se ejecuta en cientos de millones de dispositivos de todo el mundo, <br> + y ahora es compatible con estos innovadores factores de forma. + </div> + </div> + <div class="landing-body" style="margin-top: 50px;"> + <div class="landing-breakout cols"> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/wear-wordmark.png"> <img src="{@docRoot}images/home/wear.png"> + <p class="landing-small"> + Proporciona información dinámica para tus usuarios, cuando la necesiten. + </p> + <p class="landing-small"> + <a href="{@docRoot}wear/index.html">Obtener información sobre Android Wear</a> + </p> + </div> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/tv-wordmark.png"> <img src="{@docRoot}images/home/tv.png"> + <p class="landing-small"> + Crea aplicaciones para televisores y dale vida a tus contenidos. + </p> + <p class="landing-small"> + <a href="{@docRoot}tv/index.html">Obtener información sobre Android TV</a> + + </p> + </div> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/auto-wordmark.png"> <img src="{@docRoot}images/home/auto.png"> + <p class="landing-small"> + Extiende tus aplicaciones de música para los sistemas de entretenimiento para automóviles. + </p> + <p class="landing-small"> + <a href="{@docRoot}auto/index.html">Más información sobre Android Auto</a> + </p> + </div> + </div> + </div> + </div> <!-- end .wrap --> + </div> <!-- end .landing-section -->
\ No newline at end of file diff --git a/docs/html-intl/intl/ja/index.jd b/docs/html-intl/intl/ja/index.jd new file mode 100644 index 000000000000..e0153fa3161f --- /dev/null +++ b/docs/html-intl/intl/ja/index.jd @@ -0,0 +1,93 @@ +fullpage=true +page.viewport_width=970 +excludeFromSuggestions=true +page.metaDescription=Android デベロッパー向け公式サイトアプリのデベロッパーおよびデザイナー向け Android SDK とドキュメンテーションを提供します。 +page.customHeadTag=<meta name="google-site-verification" content="sa-bIAI6GKvct3f61-WpRguHq-aNjtF7xJjMTSi79as" /> + +@jd:body + +<div class="home-new-carousel-1"> + <div class="fullscreen-carousel-content"> + <div class="vcenter"> + <div class="wrap clearfix"> + + <div class="static resource-flow-layout wrap col-16"> + <div class="resource resource-card resource-card-18x6"> + + <div class="landing-section-header"> + <div class="col-10"><img src="{@docRoot}images/home/l-hero_2x.png" srcset="{@docRoot}images/home/l-hero.png 1x, {@docRoot}images/home/l-hero_2x.png 2x" width="510" style="margin:20px 30px 0 30px"></div> + <div class="col-5" style=" margin-top:70px "> + <h3 stye="font-weight:300;">Android 5.0 Lollipop</h3> + <p>Android 5.0 アップデートでは、ロック画面での通知、新しいカメラ API、OpenGL ES 3.1、新たなマテリアル デザイン インターフェースなど、ご使用のアプリにさまざまな新しい機能を提供します。</p> + <a href="{@docRoot}about/versions/lollipop.html" class="landing-button landing-primary">詳細を見る</a> + </div> + </div> + </div> + </div> + <h2> </h2> + <div style="margin-top:20px;height:115px" class="resource-widget resource-flow-layout wrap col-16 + no-section" data-query="collection:index/primary" data-resourcestyle="card" + data-sortorder="-timestamp" data-maxresults="3" data-cardsizes="6x2,6x2,6x2"></div> <!-- end .resource-widget --> + </div> <!-- end .wrap --> + </div> <!-- end .vcenter --> + </div> <!-- end .fullscreen-carousel-content --> +</div> <!-- end .fullscreen-carousel --> + +<div class="actions-bar" style="margin-top:20px"> + <div class="wrap"> + <div class="actions"> + <div><a href="{@docRoot}sdk/index.html">SDK を入手する</a></div> + <div><a href="{@docRoot}samples/index.html">サンプルを見る</a></div> + <div><a href="//www.youtube.com/user/androiddevelopers">ビデオを見る</a></div> + <div><a href="{@docRoot}distribute/googleplay/developer-console.html">アプリを管理する</a></div> + </div><!-- end .actions --> + </div><!-- end .wrap --> +</div><!-- end .actions-bar --> + + + +<div class="landing-rest-of-page"> + <div class="landing-section"> + <div class="wrap"> + <div class="landing-section-header"> + + <div class="landing-h1" style="margin-top:0px">マルチ スクリーンの世界を<br>構築しましょう</div> + <div class="landing-subhead" style="margin-top: 20px;"> + Android は世界中の数多くの携帯型デバイスで使われています。 <br> + そして今回、これらの新しいフォーム ファクタをサポートします。 + </div> + </div> + <div class="landing-body" style="margin-top: 50px;"> + <div class="landing-breakout cols"> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/wear-wordmark.png"> <img src="{@docRoot}images/home/wear.png"> + <p class="landing-small"> + いつでもどこでも、アプリのユーザーに必要な情報を提供します。 + </p> + <p class="landing-small"> + <a href="{@docRoot}wear/index.html">Android Wear の詳細を見る</a> + </p> + </div> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/tv-wordmark.png"> <img src="{@docRoot}images/home/tv.png"> + <p class="landing-small"> + 大画面向けアプリを作成して、コンテンツを生き生きと表現します。 + </p> + <p class="landing-small"> + <a href="{@docRoot}tv/index.html">Android TV の詳細を見る</a> + + </p> + </div> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/auto-wordmark.png"> <img src="{@docRoot}images/home/auto.png"> + <p class="landing-small"> + 音楽アプリを車載エンターテイメント システムに対応させます。 + </p> + <p class="landing-small"> + <a href="{@docRoot}auto/index.html">Android Auto の詳細を見る</a> + </p> + </div> + </div> + </div> + </div> <!-- end .wrap --> + </div> <!-- end .landing-section -->
\ No newline at end of file diff --git a/docs/html-intl/intl/ko/index.jd b/docs/html-intl/intl/ko/index.jd new file mode 100644 index 000000000000..59b9321d654f --- /dev/null +++ b/docs/html-intl/intl/ko/index.jd @@ -0,0 +1,93 @@ +fullpage=true +page.viewport_width=970 +excludeFromSuggestions=true +page.metaDescription=Android 개발자 공식 사이트 앱 개발자 및 디자이너에게 Android SDK 및 문서를 제공합니다. +page.customHeadTag=<meta name="google-site-verification" content="sa-bIAI6GKvct3f61-WpRguHq-aNjtF7xJjMTSi79as" /> + +@jd:body + +<div class="home-new-carousel-1"> + <div class="fullscreen-carousel-content"> + <div class="vcenter"> + <div class="wrap clearfix"> + + <div class="static resource-flow-layout wrap col-16"> + <div class="resource resource-card resource-card-18x6"> + + <div class="landing-section-header"> + <div class="col-10"><img src="{@docRoot}images/home/l-hero_2x.png" srcset="{@docRoot}images/home/l-hero.png 1x, {@docRoot}images/home/l-hero_2x.png 2x" width="510" style="margin:20px 30px 0 30px"></div> + <div class="col-5" style=" margin-top:70px "> + <h3 stye="font-weight:300;">Android 5.0 Lollipop</h3> + <p>Android 5.0 업데이트는 사용자 앱에 잠금화면상의 알림, 완전히 새로운 카메라 API, OpenGL ES 3.1, 신규 머티리얼 디자인(Material Design) 인터페이스 등 다양하고 새로운 기능을 추가합니다.</p> + <a href="{@docRoot}about/versions/lollipop.html" class="landing-button landing-primary">자세히 알아보기</a> + </div> + </div> + </div> + </div> + <h2> </h2> + <div style="margin-top:20px;height:115px" class="resource-widget resource-flow-layout wrap col-16 + no-section" data-query="collection:index/primary" data-resourcestyle="card" + data-sortorder="-timestamp" data-maxresults="3" data-cardsizes="6x2,6x2,6x2"></div> <!-- end .resource-widget --> + </div> <!-- end .wrap --> + </div> <!-- end .vcenter --> + </div> <!-- end .fullscreen-carousel-content --> +</div> <!-- end .fullscreen-carousel --> + +<div class="actions-bar" style="margin-top:20px"> + <div class="wrap"> + <div class="actions"> + <div><a href="{@docRoot}sdk/index.html">SDK 받기</a></div> + <div><a href="{@docRoot}samples/index.html">샘플 둘러보기</a></div> + <div><a href="//www.youtube.com/user/androiddevelopers">비디오 시청</a></div> + <div><a href="{@docRoot}distribute/googleplay/developer-console.html">앱 관리</a></div> + </div><!-- end .actions --> + </div><!-- end .wrap --> +</div><!-- end .actions-bar --> + + + +<div class="landing-rest-of-page"> + <div class="landing-section"> + <div class="wrap"> + <div class="landing-section-header"> + + <div class="landing-h1" style="margin-top:0px">멀티스크린 월드에 맞게 만들기</div> + <div class="landing-subhead" style="margin-top: 20px;"> + Android는 전 세계 수억 개의 휴대 기기에서 구동되고 있으며, <br> + 이제 이 흥미진진하고 새로운 폼팩터를 지원합니다. + </div> + </div> + <div class="landing-body" style="margin-top: 50px;"> + <div class="landing-breakout cols"> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/wear-wordmark.png"> <img src="{@docRoot}images/home/wear.png"> + <p class="landing-small"> + 사용자가 필요로 할 때 언제든지 실시간으로 정보를 제공합니다. + </p> + <p class="landing-small"> + <a href="{@docRoot}wear/index.html">Android Wear에 대해 알아보세요</a> + </p> + </div> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/tv-wordmark.png"> <img src="{@docRoot}images/home/tv.png"> + <p class="landing-small"> + 대형 스크린에 적합한 앱과 컨텐츠를 구성하세요. + </p> + <p class="landing-small"> + <a href="{@docRoot}tv/index.html">Android TV에 대해 알아보세요</a> + + </p> + </div> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/auto-wordmark.png"> <img src="{@docRoot}images/home/auto.png"> + <p class="landing-small"> + 음악 앱을 자동차 엔터테인먼트 시스템에 적용해보세요. + </p> + <p class="landing-small"> + <a href="{@docRoot}auto/index.html">Android Auto에 대해 알아보세요</a> + </p> + </div> + </div> + </div> + </div> <!-- end .wrap --> + </div> <!-- end .landing-section -->
\ No newline at end of file diff --git a/docs/html-intl/intl/pt-br/index.jd b/docs/html-intl/intl/pt-br/index.jd new file mode 100644 index 000000000000..bf6c57d59cf5 --- /dev/null +++ b/docs/html-intl/intl/pt-br/index.jd @@ -0,0 +1,93 @@ +fullpage=true +page.viewport_width=970 +excludeFromSuggestions=true +page.metaDescription=O site oficial dos desenvolvedores Android. Fornece o Android SDK e a documentação para desenvolvedores e projetistas de aplicativos. +page.customHeadTag=<meta name="google-site-verification" content="sa-bIAI6GKvct3f61-WpRguHq-aNjtF7xJjMTSi79as" /> + +@jd:body + +<div class="home-new-carousel-1"> + <div class="fullscreen-carousel-content"> + <div class="vcenter"> + <div class="wrap clearfix"> + + <div class="static resource-flow-layout wrap col-16"> + <div class="resource resource-card resource-card-18x6"> + + <div class="landing-section-header"> + <div class="col-10"><img src="{@docRoot}images/home/l-hero_2x.png" srcset="{@docRoot}images/home/l-hero.png 1x, {@docRoot}images/home/l-hero_2x.png 2x" width="510" style="margin:20px 30px 0 30px"></div> + <div class="col-5" style=" margin-top:70px "> + <h3 stye="font-weight:300;">Android 5.0 Lollipop</h3> + <p>A atualização do Android 5.0 adiciona diversos novos recursos aos aplicativos, como notificações na tela de bloqueio, uma API de câmera totalmente nova, OpenGL ES 3.1, a nova interface do Material Design e muito mais.</p> + <a href="{@docRoot}about/versions/lollipop.html" class="landing-button landing-primary">Saiba mais</a> + </div> + </div> + </div> + </div> + <h2> </h2> + <div style="margin-top:20px;height:115px" class="resource-widget resource-flow-layout wrap col-16 + no-section" data-query="collection:index/primary" data-resourcestyle="card" + data-sortorder="-timestamp" data-maxresults="3" data-cardsizes="6x2,6x2,6x2"></div> <!-- end .resource-widget --> + </div> <!-- end .wrap --> + </div> <!-- end .vcenter --> + </div> <!-- end .fullscreen-carousel-content --> +</div> <!-- end .fullscreen-carousel --> + +<div class="actions-bar" style="margin-top:20px"> + <div class="wrap"> + <div class="actions"> + <div><a href="{@docRoot}sdk/index.html">Obtenha o SDK</a></div> + <div><a href="{@docRoot}samples/index.html">Procure amostras</a></div> + <div><a href="//www.youtube.com/user/androiddevelopers">Assista a vídeos</a></div> + <div><a href="{@docRoot}distribute/googleplay/developer-console.html">Gerencie seus aplicativos</a></div> + </div><!-- end .actions --> + </div><!-- end .wrap --> +</div><!-- end .actions-bar --> + + + +<div class="landing-rest-of-page"> + <div class="landing-section"> + <div class="wrap"> + <div class="landing-section-header"> + + <div class="landing-h1" style="margin-top:0px">Crie para um mundo multitela</div> + <div class="landing-subhead" style="margin-top: 20px;"> + O Android funciona em milhões de dispositivos portáteis em todo o mundo <br> + e agora é compatível com esses novos e empolgantes recursos. + </div> + </div> + <div class="landing-body" style="margin-top: 50px;"> + <div class="landing-breakout cols"> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/wear-wordmark.png"><img src="{@docRoot}images/home/wear.png"> + <p class="landing-small"> + Forneça informações constantemente aos usuários, sempre que precisarem. + </p> + <p class="landing-small"> + <a href="{@docRoot}wear/index.html">Conheça o Android Wear</a> + </p> + </div> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/tv-wordmark.png"> <img src="{@docRoot}images/home/tv.png"> + <p class="landing-small"> + Crie aplicativos para a telona e dê vida ao conteúdo. + </p> + <p class="landing-small"> + <a href="{@docRoot}tv/index.html">Conheça o Android TV</a> + + </p> + </div> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/auto-wordmark.png"> <img src="{@docRoot}images/home/auto.png"> + <p class="landing-small"> + Estenda seus aplicativos de música a sistema de entretenimento de automóveis. + </p> + <p class="landing-small"> + <a href="{@docRoot}auto/index.html">Conheça o Android Auto</a> + </p> + </div> + </div> + </div> + </div> <!-- end .wrap --> + </div> <!-- end .landing-section -->
\ No newline at end of file diff --git a/docs/html-intl/intl/ru/index.jd b/docs/html-intl/intl/ru/index.jd new file mode 100644 index 000000000000..eb7ffe4d603b --- /dev/null +++ b/docs/html-intl/intl/ru/index.jd @@ -0,0 +1,93 @@ +fullpage=true +page.viewport_width=970 +excludeFromSuggestions=true +page.metaDescription=Официальный сайт для разработчиков Android. На этом сайте вы найдете пакеты Android SDK и документацию для дизайнеров и разработчиков приложений. +page.customHeadTag=<meta name="google-site-verification" content="sa-bIAI6GKvct3f61-WpRguHq-aNjtF7xJjMTSi79as" /> + +@jd:body + +<div class="home-new-carousel-1"> + <div class="fullscreen-carousel-content"> + <div class="vcenter"> + <div class="wrap clearfix"> + + <div class="static resource-flow-layout wrap col-16"> + <div class="resource resource-card resource-card-18x6"> + + <div class="landing-section-header"> + <div class="col-10"><img src="{@docRoot}images/home/l-hero_2x.png" srcset="{@docRoot}images/home/l-hero.png 1x, {@docRoot}images/home/l-hero_2x.png 2x" width="510" style="margin:20px 30px 0 30px"></div> + <div class="col-5" style=" margin-top:70px "> + <h3 stye="font-weight:300;">Android 5.0 Lollipop</h3> + <p>Обновление Android 5.0 содержит различные новые возможности для приложений: уведомления на заблокированном экране, совершено новый API камеры, OpenGL ES 3.1, новый интерфейс Material Design и множество других функций.</p> + <a href="{@docRoot}about/versions/lollipop.html" class="landing-button landing-primary">Подробнее</a> + </div> + </div> + </div> + </div> + <h2> </h2> + <div style="margin-top:20px;height:115px" class="resource-widget resource-flow-layout wrap col-16 + no-section" data-query="collection:index/primary" data-resourcestyle="card" + data-sortorder="-timestamp" data-maxresults="3" data-cardsizes="6x2,6x2,6x2"></div> <!-- end .resource-widget --> + </div> <!-- end .wrap --> + </div> <!-- end .vcenter --> + </div> <!-- end .fullscreen-carousel-content --> +</div> <!-- end .fullscreen-carousel --> + +<div class="actions-bar" style="margin-top:20px"> + <div class="wrap"> + <div class="actions"> + <div><a href="{@docRoot}sdk/index.html">Пакет SDK</a></div> + <div><a href="{@docRoot}samples/index.html">Примеры</a></div> + <div><a href="//www.youtube.com/user/androiddevelopers">Видеоролики</a></div> + <div><a href="{@docRoot}distribute/googleplay/developer-console.html">Управление приложениями</a></div> + </div><!-- end .actions --> + </div><!-- end .wrap --> +</div><!-- end .actions-bar --> + + + +<div class="landing-rest-of-page"> + <div class="landing-section"> + <div class="wrap"> + <div class="landing-section-header"> + + <div class="landing-h1" style="margin-top:0px">ОС для многоэкранных устройств</div> + <div class="landing-subhead" style="margin-top: 20px;"> + Сотни миллионов мобильных устройств по всему миру работают под управлением операционной системы Android. <br> + А теперь эта система радует и обладателей устройств других форм-факторов. + </div> + </div> + <div class="landing-body" style="margin-top: 50px;"> + <div class="landing-breakout cols"> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/wear-wordmark.png"> <img src="{@docRoot}images/home/wear.png"> + <p class="landing-small"> + Предоставляйте пользователям информацию прямо на ходу, когда бы им это ни потребовалось. + </p> + <p class="landing-small"> + <a href="{@docRoot}wear/index.html">Подробнее об Android Wear</a> + </p> + </div> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/tv-wordmark.png"> <img src="{@docRoot}images/home/tv.png"> + <p class="landing-small"> + Создавайте приложения для использования на большом экране телевизора и разрабатывайте динамичный контент. + </p> + <p class="landing-small"> + <a href="{@docRoot}tv/index.html">Подробнее об Android TV</a> + + </p> + </div> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/auto-wordmark.png"> <img src="{@docRoot}images/home/auto.png"> + <p class="landing-small"> + Автомобильные мультимедийные системы — прекрасная возможность расширить список поддерживаемых устройств для музыкальных приложений. + </p> + <p class="landing-small"> + <a href="{@docRoot}auto/index.html">Подробнее об Android Auto</a> + </p> + </div> + </div> + </div> + </div> <!-- end .wrap --> + </div> <!-- end .landing-section -->
\ No newline at end of file diff --git a/docs/html-intl/intl/zh-cn/index.jd b/docs/html-intl/intl/zh-cn/index.jd index 590332f9d0e6..1c2fb9909d26 100644 --- a/docs/html-intl/intl/zh-cn/index.jd +++ b/docs/html-intl/intl/zh-cn/index.jd @@ -1,15 +1,11 @@ fullpage=true page.viewport_width=970 excludeFromSuggestions=true -page.metaDescription=The official site for Android developers. Provides the Android SDK and documentation for app developers and designers. +page.metaDescription=Android 开发人员的官方网站。为应用开发人员以及设计师提供 Android SDK 和文档。 page.customHeadTag=<meta name="google-site-verification" content="sa-bIAI6GKvct3f61-WpRguHq-aNjtF7xJjMTSi79as" /> @jd:body - - - - <div class="home-new-carousel-1"> <div class="fullscreen-carousel-content"> <div class="vcenter"> @@ -19,38 +15,31 @@ page.customHeadTag=<meta name="google-site-verification" content="sa-bIAI6GKvct3 <div class="resource resource-card resource-card-18x6"> <div class="landing-section-header"> - <div class="col-10"><img src="{@docRoot}images/home/l-hero_2x.png" - srcset="{@docRoot}images/home/l-hero.png 1x, {@docRoot}images/home/l-hero_2x.png 2x" - width="510" style="margin:20px 30px 0 30px"></div> + <div class="col-10"><img src="{@docRoot}images/home/l-hero_2x.png" srcset="{@docRoot}images/home/l-hero.png 1x, {@docRoot}images/home/l-hero_2x.png 2x" width="510" style="margin:20px 30px 0 30px"></div> <div class="col-5" style=" margin-top:70px "> <h3 stye="font-weight:300;">Android 5.0 Lollipop</h3> - <p>在 Android 5.0 的版本更新中,我们添加了多种可用于你的应用程序的新功能,比如锁屏通知,一个全新的相机API,OpenGL ES 3.1,以及新的 Material Design 界面等等。</p> + <p>Android 5.0 更新将为您的应用增添各种新功能,例如锁定屏幕通知、全新的相机 API、OpenGL ES 3.1、全新的 Material Design 界面等等。</p> <a href="{@docRoot}about/versions/lollipop.html" class="landing-button landing-primary">了解详情</a> </div> </div> </div> </div> <h2> </h2> - - <div style="margin-top:20px" class="resource-widget resource-flow-layout wrap col-16 - no-section" data-query="collection:index/primary/zhcn" data-resourcestyle="card" - data-sortorder="-timestamp" data-maxresults="3" data-cardsizes="6x2,6x2,6x2"></div> - + <div style="margin-top:20px;height:115px" class="resource-widget resource-flow-layout wrap col-16 + no-section" data-query="collection:index/primary" data-resourcestyle="card" + data-sortorder="-timestamp" data-maxresults="3" data-cardsizes="6x2,6x2,6x2"></div> <!-- end .resource-widget --> </div> <!-- end .wrap --> </div> <!-- end .vcenter --> </div> <!-- end .fullscreen-carousel-content --> </div> <!-- end .fullscreen-carousel --> - - - <div class="actions-bar" style="margin-top:20px"> <div class="wrap"> <div class="actions"> - <div><a href="/sdk/index.html">下载 SDK</a></div> - <div><a href="/samples/index.html">浏览示例</a></div> + <div><a href="{@docRoot}sdk/index.html">获得 SDK</a></div> + <div><a href="{@docRoot}samples/index.html">浏览示例</a></div> <div><a href="//www.youtube.com/user/androiddevelopers">观看视频</a></div> - <div><a href="/distribute/googleplay/developer-console.html">管理应用</a></div> + <div><a href="{@docRoot}distribute/googleplay/developer-console.html">管理您的应用</a></div> </div><!-- end .actions --> </div><!-- end .wrap --> </div><!-- end .actions-bar --> @@ -61,44 +50,41 @@ page.customHeadTag=<meta name="google-site-verification" content="sa-bIAI6GKvct3 <div class="landing-section"> <div class="wrap"> <div class="landing-section-header"> - - <div class="landing-h1" style="margin-top:0px">专为跨屏世界打造</div> - <div class="landing-subhead" style="margin-top:20px"> - 全球数亿手持设备安装的都是 Android 系统。<br /> - 现在 Android 系统还支持以下这些备受期待的新设备。 + + <div class="landing-h1" style="margin-top:0px">专为多屏幕时代而设</div> + <div class="landing-subhead" style="margin-top: 20px;"> + Android 在全球各地的数亿台手持设备上运行, <br> + 如今更支持下列激动人心的新设备和配置。 </div> </div> - <div class="landing-body" style="margin-top:50px"> + <div class="landing-body" style="margin-top: 50px;"> <div class="landing-breakout cols"> <div class="col-3-wide"> - <img src="{@docRoot}images/home/wear-wordmark.png" /> - <img src="{@docRoot}images/home/wear.png" /> + <img src="{@docRoot}images/home/wear-wordmark.png"> <img src="{@docRoot}images/home/wear.png"> <p class="landing-small"> - 让用户随时随地获得需要的信息。 + 让您的用户即便在途中亦能随时随地获得所需的信息。 </p> <p class="landing-small"> - <a href="/wear/index.html">了解 Android Wear</a> + <a href="{@docRoot}wear/index.html">了解关于 Android Wear 的信息</a> </p> </div> <div class="col-3-wide"> - <img src="{@docRoot}images/home/tv-wordmark.png" /> - <img src="{@docRoot}images/home/tv.png" /> + <img src="{@docRoot}images/home/tv-wordmark.png"> <img src="{@docRoot}images/home/tv.png"> <p class="landing-small"> - 针对大屏幕打造应用,使你的内容引人入胜。 + 将您的应用搬上大屏幕,使您的内容栩栩如生。 </p> <p class="landing-small"> - <a href="/tv/index.html">了解 Android TV</a> + <a href="{@docRoot}tv/index.html">了解关于 Android TV 的信息</a> </p> </div> <div class="col-3-wide"> - <img src="{@docRoot}images/home/auto-wordmark.png" /> - <img src="{@docRoot}images/home/auto.png" /> + <img src="{@docRoot}images/home/auto-wordmark.png"> <img src="{@docRoot}images/home/auto.png"> <p class="landing-small"> - 将你的音乐应用扩展到车载娱乐系统。 + 将您的音乐应用扩展至车载娱乐系统。 </p> <p class="landing-small"> - <a href="/auto/index.html">了解 Android Auto</a> + <a href="{@docRoot}auto/index.html">了解关于 Android Auto 的信息</a> </p> </div> </div> diff --git a/docs/html-intl/intl/zh-tw/index.jd b/docs/html-intl/intl/zh-tw/index.jd new file mode 100644 index 000000000000..56ae4cf574bd --- /dev/null +++ b/docs/html-intl/intl/zh-tw/index.jd @@ -0,0 +1,92 @@ +fullpage=true +page.viewport_width=970excludeFromSuggestions=true +page.metaDescription=適用於 Android 開發人員的官方網站。提供適用於應用程式開發人員與設計師的 Android SDK 與文件。 +page.customHeadTag=<meta name="google-site-verification" content="sa-bIAI6GKvct3f61-WpRguHq-aNjtF7xJjMTSi79as" /> + +@jd:body + +<div class="home-new-carousel-1"> + <div class="fullscreen-carousel-content"> + <div class="vcenter"> + <div class="wrap clearfix"> + + <div class="static resource-flow-layout wrap col-16"> + <div class="resource resource-card resource-card-18x6"> + + <div class="landing-section-header"> + <div class="col-10"><img src="{@docRoot}images/home/l-hero_2x.png" srcset="{@docRoot}images/home/l-hero.png 1x, {@docRoot}images/home/l-hero_2x.png 2x" width="510" style="margin:20px 30px 0 30px"></div> + <div class="col-5" style=" margin-top:70px "> + <h3 stye="font-weight:300;">Android 5.0 棒棒糖</h3> + <p>Android 5.0 更新新增了許多新功能到您的應用程式,例如鎖定螢幕上的通知、全新的相機 API、OpenGL ES 3.1、新的材料設計介面,還有更多其他功能。</p> + <a href="{@docRoot}about/versions/lollipop.html" class="landing-button landing-primary">深入了解</a> + </div> + </div> + </div> + </div> + <h2> </h2> + <div style="margin-top:20px;height:115px" class="resource-widget resource-flow-layout wrap col-16 + no-section" data-query="collection:index/primary" data-resourcestyle="card" + data-sortorder="-timestamp" data-maxresults="3" data-cardsizes="6x2,6x2,6x2"></div> <!-- end .resource-widget --> + </div> <!-- end .wrap --> + </div> <!-- end .vcenter --> + </div> <!-- end .fullscreen-carousel-content --> +</div> <!-- end .fullscreen-carousel --> + +<div class="actions-bar" style="margin-top:20px"> + <div class="wrap"> + <div class="actions"> + <div><a href="{@docRoot}sdk/index.html">取得 SDK</a></div> + <div><a href="{@docRoot}samples/index.html">瀏覽範例</a></div> + <div><a href="//www.youtube.com/user/androiddevelopers">觀賞影片</a></div> + <div><a href="{@docRoot}distribute/googleplay/developer-console.html">管理您的應用程式</a></div> + </div><!-- end .actions --> + </div><!-- end .wrap --> +</div><!-- end .actions-bar --> + + + +<div class="landing-rest-of-page"> + <div class="landing-section"> + <div class="wrap"> + <div class="landing-section-header"> + + <div class="landing-h1" style="margin-top:0px">針對多螢幕世界建置</div> + <div class="landing-subhead" style="margin-top: 20px;"> + Android 在全球數百萬部手持式裝置上執行, <br> + 而且它現在支援這些令人興奮、各種尺寸的裝置。 + </div> + </div> + <div class="landing-body" style="margin-top: 50px;"> + <div class="landing-breakout cols"> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/wear-wordmark.png"> <img src="{@docRoot}images/home/wear.png"> + <p class="landing-small"> + 為您的使用者提供可隨時隨地存取的資訊。 + </p> + <p class="landing-small"> + <a href="{@docRoot}wear/index.html">了解 Android Wear</a> + </p> + </div> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/tv-wordmark.png"> <img src="{@docRoot}images/home/tv.png"> + <p class="landing-small"> + 為大螢幕建置您的應用程式,並將您的內容帶到生活中。 + </p> + <p class="landing-small"> + <a href="{@docRoot}tv/index.html">了解 Android TV</a> + + </p> + </div> + <div class="col-3-wide"> + <img src="{@docRoot}images/home/auto-wordmark.png"> <img src="{@docRoot}images/home/auto.png"> + <p class="landing-small"> + 將您的音樂應用程式延伸到車用娛樂系統。 + </p> + <p class="landing-small"> + <a href="{@docRoot}auto/index.html">了解 Android Auto</a> + </p> + </div> + </div> + </div> + </div> <!-- end .wrap --> + </div> <!-- end .landing-section -->
\ No newline at end of file diff --git a/docs/html/training/articles/keystore.jd b/docs/html/training/articles/keystore.jd index a4fc2d23adfe..217db8149aee 100644 --- a/docs/html/training/articles/keystore.jd +++ b/docs/html/training/articles/keystore.jd @@ -29,7 +29,9 @@ page.title=Android Keystore System <p>The Android Keystore system lets you store cryptographic keys in a container to make it more difficult to extract from the device. Once keys are in the keystore, they can be used for cryptographic operations with the key material - remaining non-exportable.</p> + remaining non-exportable. Moreover, it offers facilities to restrict when and + how keys can be used, such as requiring user authentication for key use or + restricting encryption keys to be used only in certain block modes.</p> <p>The Keystore system is used by the {@link android.security.KeyChain} API as well as the Android @@ -112,3 +114,27 @@ and {@link java.security.KeyPairGenerator} or <p>Similarly, verify data with the {@link java.security.Signature#verify(byte[])} method:</p> {@sample development/samples/ApiDemos/src/com/example/android/apis/security/KeyStoreUsage.java verify} + +<h3 id="UserAuthentication">Requiring User Authentication For Key Use</h3> + +<p>When generating or importing a key into the {@code AndroidKeyStore} you can specify that the key +can only be used if user has been authenticated. The user is authenticated using a subset of their +secure lock screen credentials. This is a security measure which makes it possible to generate +cryptographic assertions about the user having been authenticated. + +<p>When a key is configured to require user authentication, it is also configured to operate in one +of the two modes: +<ul> +<li>User authentication is valid for a duration of time. All keys in this mode are authorized + for use as soon as the user unlocks the secure lock screen or confirms their secure lock screen + credentials using the {@link android.app.KeyguardManager#createConfirmDeviceCredentialIntent(CharSequence, CharSequence) KeyguardManager.createConfirmDeviceCredentialIntent} + flow. Each key specifies for how long the authorization remains valid for that key. Such keys + can only be generated or imported if the secure lock screen is enabled (see {@link android.app.KeyguardManager#isKeyguardSecure Keyguard.isKeyguardSecure}). + These keys become permanently invalidated once the secure lock screen is disabled or forcibly + reset (e.g. by a Device Admin).</li> +<li>User authentication is required for every use of the key. In this mode, a specific operation + involving a specific key is authorized by the user. Currently, the only means of such + authorization is fingerprint authentication: {@link android.hardware.fingerprint.FingerprintManager#authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, int) FingerprintManager.authenticate}. + Such keys can only be generated or imported if at least one fingerprint is enrolled (see {@link android.hardware.fingerprint.FingerprintManager#hasEnrolledFingerprints() FingerprintManager.hasEnrolledFingerprints}). + These keys become permanently invalidated once all fingerprints are unenrolled.</li> +</ul> diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index c3d8cfa95b14..e5b461270a00 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -564,8 +564,6 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { if (drawable != null) { drawable.setCallback(this); - drawable.setLayoutDirection(getLayoutDirection()); - drawable.setLevel(getLevel()); } childDrawable.mDrawable = drawable; diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java index c259c25b0e5c..ed91d7080054 100644 --- a/keystore/java/android/security/AndroidKeyStore.java +++ b/keystore/java/android/security/AndroidKeyStore.java @@ -529,27 +529,10 @@ public class AndroidKeyStore extends KeyStoreSpi { KeymasterUtils.getKeymasterPaddingsFromJcaSignaturePaddings( params.getSignaturePaddings())); args.addInts(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings); - if (params.getUserAuthenticators() == 0) { - args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED); - } else { - args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, - KeyStoreKeyProperties.UserAuthenticator.allToKeymaster( - params.getUserAuthenticators())); - long secureUserId = GateKeeper.getSecureUserId(); - if (secureUserId == 0) { - throw new IllegalStateException("Secure lock screen must be enabled" - + " to import keys requiring user authentication"); - } - args.addLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, secureUserId); - } - if (params.isInvalidatedOnNewFingerprintEnrolled()) { - // TODO: Add the invalidate on fingerprint enrolled constraint once Keymaster supports - // that. - } - if (params.getUserAuthenticationValidityDurationSeconds() != -1) { - args.addInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, - params.getUserAuthenticationValidityDurationSeconds()); - } + KeymasterUtils.addUserAuthArgs(args, + params.getContext(), + params.isUserAuthenticationRequired(), + params.getUserAuthenticationValidityDurationSeconds()); args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, (params.getKeyValidityStart() != null) ? params.getKeyValidityStart() : new Date(0)); diff --git a/keystore/java/android/security/KeyGeneratorSpec.java b/keystore/java/android/security/KeyGeneratorSpec.java index 7ecc47e4014f..8f135a6f4b7b 100644 --- a/keystore/java/android/security/KeyGeneratorSpec.java +++ b/keystore/java/android/security/KeyGeneratorSpec.java @@ -51,9 +51,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { private final String[] mEncryptionPaddings; private final String[] mBlockModes; private final boolean mRandomizedEncryptionRequired; - private final @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators; + private final boolean mUserAuthenticationRequired; private final int mUserAuthenticationValidityDurationSeconds; - private final boolean mInvalidatedOnNewFingerprintEnrolled; private KeyGeneratorSpec( Context context, @@ -67,9 +66,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { String[] encryptionPaddings, String[] blockModes, boolean randomizedEncryptionRequired, - @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators, - int userAuthenticationValidityDurationSeconds, - boolean invalidatedOnNewFingerprintEnrolled) { + boolean userAuthenticationRequired, + int userAuthenticationValidityDurationSeconds) { if (context == null) { throw new IllegalArgumentException("context == null"); } else if (TextUtils.isEmpty(keyStoreAlias)) { @@ -92,9 +90,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(encryptionPaddings)); mBlockModes = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(blockModes)); mRandomizedEncryptionRequired = randomizedEncryptionRequired; - mUserAuthenticators = userAuthenticators; + mUserAuthenticationRequired = userAuthenticationRequired; mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; - mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled; } /** @@ -188,18 +185,17 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { } /** - * Gets the set of user authenticators which protect access to this key. The key can only be - * used iff the user has authenticated to at least one of these user authenticators. + * Returns {@code true} if user authentication is required for this key to be used. * - * @return user authenticators or {@code 0} if the key can be used without user authentication. + * @see #getUserAuthenticationValidityDurationSeconds() */ - public @KeyStoreKeyProperties.UserAuthenticatorEnum int getUserAuthenticators() { - return mUserAuthenticators; + public boolean isUserAuthenticationRequired() { + return mUserAuthenticationRequired; } /** - * Gets the duration of time (seconds) for which this key can be used after the user - * successfully authenticates to one of the associated user authenticators. + * Gets the duration of time (seconds) for which this key can be used after the user is + * successfully authenticated. * * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication * is required for every use of the key. @@ -209,17 +205,6 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { } /** - * Returns {@code true} if this key must be permanently invalidated once a new fingerprint is - * enrolled. This constraint only has effect if fingerprint reader is one of the user - * authenticators protecting access to this key. - * - * @see #getUserAuthenticators() - */ - public boolean isInvalidatedOnNewFingerprintEnrolled() { - return mInvalidatedOnNewFingerprintEnrolled; - } - - /** * Returns {@code true} if the key must be encrypted in the {@link java.security.KeyStore}. */ public boolean isEncryptionRequired() { @@ -238,9 +223,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { private String[] mEncryptionPaddings; private String[] mBlockModes; private boolean mRandomizedEncryptionRequired = true; - private @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators; + private boolean mUserAuthenticationRequired; private int mUserAuthenticationValidityDurationSeconds = -1; - private boolean mInvalidatedOnNewFingerprintEnrolled; /** * Creates a new instance of the {@code Builder} with the given {@code context}. The @@ -416,32 +400,35 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { } /** - * Sets the user authenticators which protect access to this key. The key can only be used - * iff the user has authenticated to at least one of these user authenticators. + * Sets whether user authentication is required to use this key. * * <p>By default, the key can be used without user authentication. * - * @param userAuthenticators user authenticators or empty list if this key can be accessed - * without user authentication. + * <p>When user authentication is required, the user authorizes the use of the key by + * authenticating to this Android device using a subset of their secure lock screen + * credentials. Different authentication methods are used depending on whether the every + * use of the key must be authenticated (as specified by + * {@link #setUserAuthenticationValidityDurationSeconds(int)}). + * <a href="{@docRoot}training/articles/keystore.html#UserAuthentication">More + * information</a>. * * @see #setUserAuthenticationValidityDurationSeconds(int) */ - public Builder setUserAuthenticators( - @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators) { - mUserAuthenticators = userAuthenticators; + public Builder setUserAuthenticationRequired(boolean required) { + mUserAuthenticationRequired = required; return this; } /** - * Sets the duration of time (seconds) for which this key can be used after the user - * successfully authenticates to one of the associated user authenticators. + * Sets the duration of time (seconds) for which this key can be used after the user is + * successfully authenticated. This has effect only if user authentication is required. * * <p>By default, the user needs to authenticate for every use of the key. * * @param seconds duration in seconds or {@code 0} if the user needs to authenticate for * every use of the key. * - * @see #setUserAuthenticators(int) + * @see #setUserAuthenticationRequired(boolean) */ public Builder setUserAuthenticationValidityDurationSeconds(int seconds) { mUserAuthenticationValidityDurationSeconds = seconds; @@ -449,20 +436,6 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { } /** - * Sets whether this key must be invalidated (permanently) once a new fingerprint is - * enrolled. This only has effect if fingerprint reader is one of the user authenticators - * protecting access to the key. - * - * <p>By default, enrolling a new fingerprint does not invalidate the key. - * - * @see #setUserAuthenticators(Set) - */ - public Builder setInvalidatedOnNewFingerprintEnrolled(boolean invalidated) { - mInvalidatedOnNewFingerprintEnrolled = invalidated; - return this; - } - - /** * Builds a new instance instance of {@code KeyGeneratorSpec}. * * @throws IllegalArgumentException if a required field is missing or violates a constraint. @@ -479,9 +452,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { mEncryptionPaddings, mBlockModes, mRandomizedEncryptionRequired, - mUserAuthenticators, - mUserAuthenticationValidityDurationSeconds, - mInvalidatedOnNewFingerprintEnrolled); + mUserAuthenticationRequired, + mUserAuthenticationValidityDurationSeconds); } } } diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java index 5e5cf37c3e3b..d6d37897eee4 100644 --- a/keystore/java/android/security/KeyPairGeneratorSpec.java +++ b/keystore/java/android/security/KeyPairGeneratorSpec.java @@ -95,12 +95,10 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private final boolean mRandomizedEncryptionRequired; - private final @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators; + private final boolean mUserAuthenticationRequired; private final int mUserAuthenticationValidityDurationSeconds; - private final boolean mInvalidatedOnNewFingerprintEnrolled; - /** * Parameter specification for the "{@code AndroidKeyPairGenerator}" * instance of the {@link java.security.KeyPairGenerator} API. The @@ -145,9 +143,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { String[] signaturePaddings, String[] blockModes, boolean randomizedEncryptionRequired, - @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators, - int userAuthenticationValidityDurationSeconds, - boolean invalidatedOnNewFingerprintEnrolled) { + boolean userAuthenticationRequired, + int userAuthenticationValidityDurationSeconds) { if (context == null) { throw new IllegalArgumentException("context == null"); } else if (TextUtils.isEmpty(keyStoreAlias)) { @@ -195,9 +192,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { mSignaturePaddings = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(signaturePaddings)); mBlockModes = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(blockModes)); mRandomizedEncryptionRequired = randomizedEncryptionRequired; - mUserAuthenticators = userAuthenticators; + mUserAuthenticationRequired = userAuthenticationRequired; mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; - mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled; } /** @@ -227,9 +223,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { null, // signature paddings null, // block modes false, // randomized encryption required - 0, // user authenticators - -1, // user authentication validity duration (seconds) - false // invalidate on new fingerprint enrolled + false, // user authentication required + -1 // user authentication validity duration (seconds) ); } @@ -396,44 +391,34 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { } /** - * Gets the set of user authenticators which protect access to the private key. The key can only - * be used iff the user has authenticated to at least one of these user authenticators. + * Returns {@code true} if user authentication is required for this key to be used. * * <p>This restriction applies only to private key operations. Public key operations are not * restricted. * - * @return user authenticators or {@code 0} if the key can be used without user authentication. + * @see #getUserAuthenticationValidityDurationSeconds() */ - public @KeyStoreKeyProperties.UserAuthenticatorEnum int getUserAuthenticators() { - return mUserAuthenticators; + public boolean isUserAuthenticationRequired() { + return mUserAuthenticationRequired; } /** * Gets the duration of time (seconds) for which the private key can be used after the user - * successfully authenticates to one of the associated user authenticators. + * is successfully authenticated. * * <p>This restriction applies only to private key operations. Public key operations are not * restricted. * * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication * is required for every use of the key. + * + * @see #isUserAuthenticationRequired() */ public int getUserAuthenticationValidityDurationSeconds() { return mUserAuthenticationValidityDurationSeconds; } /** - * Returns {@code true} if this key must be permanently invalidated once a new fingerprint is - * enrolled. This constraint only has effect if fingerprint reader is one of the user - * authenticators protecting access to this key. - * - * @see #getUserAuthenticators() - */ - public boolean isInvalidatedOnNewFingerprintEnrolled() { - return mInvalidatedOnNewFingerprintEnrolled; - } - - /** * Builder class for {@link KeyPairGeneratorSpec} objects. * <p> * This will build a parameter spec for use with the <a href="{@docRoot} @@ -493,12 +478,10 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private boolean mRandomizedEncryptionRequired = true; - private @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators; + private boolean mUserAuthenticationRequired; private int mUserAuthenticationValidityDurationSeconds = -1; - private boolean mInvalidatedOnNewFingerprintEnrolled; - /** * Creates a new instance of the {@code Builder} with the given * {@code context}. The {@code context} passed in may be used to pop up @@ -774,28 +757,31 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { } /** - * Sets the user authenticators which protect access to this key. The key can only be used - * iff the user has authenticated to at least one of these user authenticators. + * Sets whether user authentication is required to use this key. * * <p>By default, the key can be used without user authentication. * + * <p>When user authentication is required, the user authorizes the use of the key by + * authenticating to this Android device using a subset of their secure lock screen + * credentials. Different authentication methods are used depending on whether the every + * use of the key must be authenticated (as specified by + * {@link #setUserAuthenticationValidityDurationSeconds(int)}). + * <a href="{@docRoot}training/articles/keystore.html#UserAuthentication">More + * information</a>. + * * <p>This restriction applies only to private key operations. Public key operations are not * restricted. * - * @param userAuthenticators user authenticators or {@code 0} if this key can be accessed - * without user authentication. - * * @see #setUserAuthenticationValidityDurationSeconds(int) */ - public Builder setUserAuthenticators( - @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators) { - mUserAuthenticators = userAuthenticators; + public Builder setUserAuthenticationRequired(boolean required) { + mUserAuthenticationRequired = required; return this; } /** - * Sets the duration of time (seconds) for which this key can be used after the user - * successfully authenticates to one of the associated user authenticators. + * Sets the duration of time (seconds) for which this key can be used after the user is + * successfully authenticated. This has effect only if user authentication is required. * * <p>By default, the user needs to authenticate for every use of the key. * @@ -805,7 +791,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * @param seconds duration in seconds or {@code 0} if the user needs to authenticate for * every use of the key. * - * @see #setUserAuthenticators(int) + * @see #setUserAuthenticationRequired(boolean) */ public Builder setUserAuthenticationValidityDurationSeconds(int seconds) { mUserAuthenticationValidityDurationSeconds = seconds; @@ -813,20 +799,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { } /** - * Sets whether this key must be invalidated (permanently) once a new fingerprint is - * enrolled. This only has effect if fingerprint reader is one of the user authenticators - * protecting access to the key. - * - * <p>By default, enrolling a new fingerprint does not invalidate the key. - * - * @see #setUserAuthenticators(Set) - */ - public Builder setInvalidatedOnNewFingerprintEnrolled(boolean invalidated) { - mInvalidatedOnNewFingerprintEnrolled = invalidated; - return this; - } - - /** * Builds the instance of the {@code KeyPairGeneratorSpec}. * * @throws IllegalArgumentException if a required field is missing @@ -852,9 +824,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { mSignaturePaddings, mBlockModes, mRandomizedEncryptionRequired, - mUserAuthenticators, - mUserAuthenticationValidityDurationSeconds, - mInvalidatedOnNewFingerprintEnrolled); + mUserAuthenticationRequired, + mUserAuthenticationValidityDurationSeconds); } } } diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 8c49ff0a3eca..5d863c2d969d 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -53,6 +53,14 @@ public class KeyStore { public static final int UNDEFINED_ACTION = 9; public static final int WRONG_PASSWORD = 10; + /** + * Per operation authentication is needed before this operation is valid. + * This is returned from {@link #begin} when begin succeeds but the operation uses + * per-operation authentication and must authenticate before calling {@link #update} or + * {@link #finish}. + */ + public static final int OP_AUTH_NEEDED = 15; + // Used for UID field to indicate the calling UID. public static final int UID_SELF = -1; diff --git a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java index 293c4c9427f2..20f6042d658c 100644 --- a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java +++ b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java @@ -161,27 +161,10 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { KeymasterDefs.KM_TAG_PADDING, KeymasterUtils.getKeymasterPaddingsFromJcaEncryptionPaddings( spec.getEncryptionPaddings())); - if (spec.getUserAuthenticators() == 0) { - args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED); - } else { - args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, - KeyStoreKeyProperties.UserAuthenticator.allToKeymaster( - spec.getUserAuthenticators())); - long secureUserId = GateKeeper.getSecureUserId(); - if (secureUserId == 0) { - throw new IllegalStateException("Secure lock screen must be enabled" - + " to generate keys requiring user authentication"); - } - args.addLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, secureUserId); - } - if (spec.isInvalidatedOnNewFingerprintEnrolled()) { - // TODO: Add the invalidate on fingerprint enrolled constraint once Keymaster supports - // that. - } - if (spec.getUserAuthenticationValidityDurationSeconds() != -1) { - args.addInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, - spec.getUserAuthenticationValidityDurationSeconds()); - } + KeymasterUtils.addUserAuthArgs(args, + spec.getContext(), + spec.isUserAuthenticationRequired(), + spec.getUserAuthenticationValidityDurationSeconds()); args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, (spec.getKeyValidityStart() != null) ? spec.getKeyValidityStart() : new Date(0)); diff --git a/keystore/java/android/security/KeyStoreKeyProperties.java b/keystore/java/android/security/KeyStoreKeyProperties.java index 206103f44908..b85ec531f245 100644 --- a/keystore/java/android/security/KeyStoreKeyProperties.java +++ b/keystore/java/android/security/KeyStoreKeyProperties.java @@ -122,101 +122,6 @@ public abstract class KeyStoreKeyProperties { } @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, - value = {UserAuthenticator.LOCK_SCREEN, UserAuthenticator.FINGERPRINT_READER}) - public @interface UserAuthenticatorEnum {} - - /** - * User authenticators which can be used to restrict/protect access to keys. - */ - public static abstract class UserAuthenticator { - private UserAuthenticator() {} - - /** Lock screen. */ - public static final int LOCK_SCREEN = 1 << 0; - - /** Fingerprint reader/sensor. */ - public static final int FINGERPRINT_READER = 1 << 1; - - /** - * @hide - */ - public static int toKeymaster(@UserAuthenticatorEnum int userAuthenticator) { - switch (userAuthenticator) { - case LOCK_SCREEN: - return KeymasterDefs.HW_AUTH_PASSWORD; - case FINGERPRINT_READER: - return KeymasterDefs.HW_AUTH_FINGERPRINT; - default: - throw new IllegalArgumentException( - "Unknown user authenticator: " + userAuthenticator); - } - } - - /** - * @hide - */ - public static @UserAuthenticatorEnum int fromKeymaster(int userAuthenticator) { - switch (userAuthenticator) { - case KeymasterDefs.HW_AUTH_PASSWORD: - return LOCK_SCREEN; - case KeymasterDefs.HW_AUTH_FINGERPRINT: - return FINGERPRINT_READER; - default: - throw new IllegalArgumentException( - "Unknown user authenticator: " + userAuthenticator); - } - } - - /** - * @hide - */ - public static int allToKeymaster(@UserAuthenticatorEnum int userAuthenticators) { - int result = 0; - int userAuthenticator = 1; - while (userAuthenticators != 0) { - if ((userAuthenticators & 1) != 0) { - result |= toKeymaster(userAuthenticator); - } - userAuthenticators >>>= 1; - userAuthenticator <<= 1; - } - return result; - } - - /** - * @hide - */ - public static @UserAuthenticatorEnum int allFromKeymaster(int userAuthenticators) { - @UserAuthenticatorEnum int result = 0; - int userAuthenticator = 1; - while (userAuthenticators != 0) { - if ((userAuthenticators & 1) != 0) { - result |= fromKeymaster(userAuthenticator); - } - userAuthenticators >>>= 1; - userAuthenticator <<= 1; - } - return result; - } - - /** - * @hide - */ - public static String toString(@UserAuthenticatorEnum int userAuthenticator) { - switch (userAuthenticator) { - case LOCK_SCREEN: - return "LOCK_SCREEN"; - case FINGERPRINT_READER: - return "FINGERPRINT_READER"; - default: - throw new IllegalArgumentException( - "Unknown user authenticator: " + userAuthenticator); - } - } - } - - @Retention(RetentionPolicy.SOURCE) @IntDef({Origin.GENERATED, Origin.IMPORTED, Origin.UNKNOWN}) public @interface OriginEnum {} diff --git a/keystore/java/android/security/KeyStoreKeySpec.java b/keystore/java/android/security/KeyStoreKeySpec.java index a89e4dd0f5b1..96d58d824011 100644 --- a/keystore/java/android/security/KeyStoreKeySpec.java +++ b/keystore/java/android/security/KeyStoreKeySpec.java @@ -36,10 +36,9 @@ public class KeyStoreKeySpec implements KeySpec { private final String[] mSignaturePaddings; private final String[] mDigests; private final String[] mBlockModes; - private final @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators; - private final @KeyStoreKeyProperties.UserAuthenticatorEnum int mTeeEnforcedUserAuthenticators; + private final boolean mUserAuthenticationRequired; private final int mUserAuthenticationValidityDurationSeconds; - private final boolean mInvalidatedOnNewFingerprintEnrolled; + private final boolean mUserAuthenticationRequirementTeeEnforced; /** * @hide @@ -56,10 +55,9 @@ public class KeyStoreKeySpec implements KeySpec { String[] signaturePaddings, String[] digests, String[] blockModes, - @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators, - @KeyStoreKeyProperties.UserAuthenticatorEnum int teeEnforcedUserAuthenticators, + boolean userAuthenticationRequired, int userAuthenticationValidityDurationSeconds, - boolean invalidatedOnNewFingerprintEnrolled) { + boolean userAuthenticationRequirementTeeEnforced) { mKeystoreAlias = keystoreKeyAlias; mTeeBacked = teeBacked; mOrigin = origin; @@ -74,10 +72,9 @@ public class KeyStoreKeySpec implements KeySpec { ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(signaturePaddings)); mDigests = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(digests)); mBlockModes = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(blockModes)); - mUserAuthenticators = userAuthenticators; - mTeeEnforcedUserAuthenticators = teeEnforcedUserAuthenticators; + mUserAuthenticationRequired = userAuthenticationRequired; mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; - mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled; + mUserAuthenticationRequirementTeeEnforced = userAuthenticationRequirementTeeEnforced; } /** @@ -172,43 +169,34 @@ public class KeyStoreKeySpec implements KeySpec { } /** - * Gets the set of user authenticators which protect access to the key. The key can only be used - * iff the user has authenticated to at least one of these user authenticators. + * Returns {@code true} if user authentication is required for this key to be used. * - * @return user authenticators or {@code 0} if the key can be used without user authentication. + * @see #getUserAuthenticationValidityDurationSeconds() */ - public @KeyStoreKeyProperties.UserAuthenticatorEnum int getUserAuthenticators() { - return mUserAuthenticators; + public boolean isUserAuthenticationRequired() { + return mUserAuthenticationRequired; } /** - * Gets the set of user authenticators for which the TEE enforces access restrictions for this - * key. This is a subset of the user authentications returned by - * {@link #getUserAuthenticators()}. - */ - public @KeyStoreKeyProperties.UserAuthenticatorEnum int getTeeEnforcedUserAuthenticators() { - return mTeeEnforcedUserAuthenticators; - } - - /** - * Gets the duration of time (seconds) for which the key can be used after the user - * successfully authenticates to one of the associated user authenticators. + * Gets the duration of time (seconds) for which this key can be used after the user is + * successfully authenticated. * * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication * is required for every use of the key. + * + * @see #isUserAuthenticationRequired() */ public int getUserAuthenticationValidityDurationSeconds() { return mUserAuthenticationValidityDurationSeconds; } /** - * Returns {@code true} if this key will be permanently invalidated once a new fingerprint is - * enrolled. This constraint only has effect if fingerprint reader is one of the user - * authenticators protecting access to this key. + * Returns {@code true} if the requirement that this key can only be used if the user has been + * authenticated if enforced by the TEE. * - * @see #getUserAuthenticators() + * @see #isUserAuthenticationRequired() */ - public boolean isInvalidatedOnNewFingerprintEnrolled() { - return mInvalidatedOnNewFingerprintEnrolled; + public boolean isUserAuthenticationRequirementTeeEnforced() { + return mUserAuthenticationRequirementTeeEnforced; } } diff --git a/keystore/java/android/security/KeyStoreParameter.java b/keystore/java/android/security/KeyStoreParameter.java index c24b74f42e20..b4747e937040 100644 --- a/keystore/java/android/security/KeyStoreParameter.java +++ b/keystore/java/android/security/KeyStoreParameter.java @@ -39,7 +39,8 @@ import javax.crypto.Cipher; * {@code KeyStore}. */ public final class KeyStoreParameter implements ProtectionParameter { - private int mFlags; + private final Context mContext; + private final int mFlags; private final Date mKeyValidityStart; private final Date mKeyValidityForOriginationEnd; private final Date mKeyValidityForConsumptionEnd; @@ -49,11 +50,12 @@ public final class KeyStoreParameter implements ProtectionParameter { private final String[] mDigests; private final String[] mBlockModes; private final boolean mRandomizedEncryptionRequired; - private final @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators; + private final boolean mUserAuthenticationRequired; private final int mUserAuthenticationValidityDurationSeconds; - private final boolean mInvalidatedOnNewFingerprintEnrolled; - private KeyStoreParameter(int flags, + private KeyStoreParameter( + Context context, + int flags, Date keyValidityStart, Date keyValidityForOriginationEnd, Date keyValidityForConsumptionEnd, @@ -63,15 +65,17 @@ public final class KeyStoreParameter implements ProtectionParameter { String[] digests, String[] blockModes, boolean randomizedEncryptionRequired, - @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators, - int userAuthenticationValidityDurationSeconds, - boolean invalidatedOnNewFingerprintEnrolled) { - if ((userAuthenticationValidityDurationSeconds < 0) + boolean userAuthenticationRequired, + int userAuthenticationValidityDurationSeconds) { + if (context == null) { + throw new IllegalArgumentException("context == null"); + } else if ((userAuthenticationValidityDurationSeconds < 0) && (userAuthenticationValidityDurationSeconds != -1)) { throw new IllegalArgumentException( "userAuthenticationValidityDurationSeconds must not be negative"); } + mContext = context; mFlags = flags; mKeyValidityStart = keyValidityStart; mKeyValidityForOriginationEnd = keyValidityForOriginationEnd; @@ -84,9 +88,15 @@ public final class KeyStoreParameter implements ProtectionParameter { mDigests = ArrayUtils.cloneIfNotEmpty(digests); mBlockModes = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(blockModes)); mRandomizedEncryptionRequired = randomizedEncryptionRequired; - mUserAuthenticators = userAuthenticators; + mUserAuthenticationRequired = userAuthenticationRequired; mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; - mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled; + } + + /** + * Gets the Android context used for operations with this instance. + */ + public Context getContext() { + return mContext; } /** @@ -198,18 +208,17 @@ public final class KeyStoreParameter implements ProtectionParameter { } /** - * Gets the set of user authenticators which protect access to this key. The key can only be - * used iff the user has authenticated to at least one of these user authenticators. + * Returns {@code true} if user authentication is required for this key to be used. * - * @return user authenticators or {@code 0} if the key can be used without user authentication. + * @see #getUserAuthenticationValidityDurationSeconds() */ - public @KeyStoreKeyProperties.UserAuthenticatorEnum int getUserAuthenticators() { - return mUserAuthenticators; + public boolean isUserAuthenticationRequired() { + return mUserAuthenticationRequired; } /** - * Gets the duration of time (seconds) for which this key can be used after the user - * successfully authenticates to one of the associated user authenticators. + * Gets the duration of time (seconds) for which this key can be used after the user is + * successfully authenticated. * * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication * is required for every use of the key. @@ -219,17 +228,6 @@ public final class KeyStoreParameter implements ProtectionParameter { } /** - * Returns {@code true} if this key must be permanently invalidated once a new fingerprint is - * enrolled. This constraint only has effect if fingerprint reader is one of the user - * authenticators protecting access to this key. - * - * @see #getUserAuthenticators() - */ - public boolean isInvalidatedOnNewFingerprintEnrolled() { - return mInvalidatedOnNewFingerprintEnrolled; - } - - /** * Builder class for {@link KeyStoreParameter} objects. * <p> * This will build protection parameters for use with the @@ -247,6 +245,7 @@ public final class KeyStoreParameter implements ProtectionParameter { * </pre> */ public final static class Builder { + private final Context mContext; private int mFlags; private Date mKeyValidityStart; private Date mKeyValidityForOriginationEnd; @@ -257,9 +256,8 @@ public final class KeyStoreParameter implements ProtectionParameter { private String[] mDigests; private String[] mBlockModes; private boolean mRandomizedEncryptionRequired = true; - private @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators; + private boolean mUserAuthenticationRequired; private int mUserAuthenticationValidityDurationSeconds = -1; - private boolean mInvalidatedOnNewFingerprintEnrolled; /** * Creates a new instance of the {@code Builder} with the given @@ -271,8 +269,7 @@ public final class KeyStoreParameter implements ProtectionParameter { if (context == null) { throw new NullPointerException("context == null"); } - - // Context is currently not used, but will be in the future. + mContext = context; } /** @@ -440,32 +437,35 @@ public final class KeyStoreParameter implements ProtectionParameter { } /** - * Sets the user authenticators which protect access to this key. The key can only be used - * iff the user has authenticated to at least one of these user authenticators. + * Sets whether user authentication is required to use this key. * * <p>By default, the key can be used without user authentication. * - * @param userAuthenticators user authenticators or {@code 0} if this key can be accessed - * without user authentication. + * <p>When user authentication is required, the user authorizes the use of the key by + * authenticating to this Android device using a subset of their secure lock screen + * credentials. Different authentication methods are used depending on whether the every + * use of the key must be authenticated (as specified by + * {@link #setUserAuthenticationValidityDurationSeconds(int)}). + * <a href="{@docRoot}training/articles/keystore.html#UserAuthentication">More + * information</a>. * * @see #setUserAuthenticationValidityDurationSeconds(int) */ - public Builder setUserAuthenticators( - @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators) { - mUserAuthenticators = userAuthenticators; + public Builder setUserAuthenticationRequired(boolean required) { + mUserAuthenticationRequired = required; return this; } /** - * Sets the duration of time (seconds) for which this key can be used after the user - * successfully authenticates to one of the associated user authenticators. + * Sets the duration of time (seconds) for which this key can be used after the user is + * successfully authenticated. This has effect only if user authentication is required. * * <p>By default, the user needs to authenticate for every use of the key. * * @param seconds duration in seconds or {@code 0} if the user needs to authenticate for * every use of the key. * - * @see #setUserAuthenticators(int) + * @see #setUserAuthenticationRequired(boolean) */ public Builder setUserAuthenticationValidityDurationSeconds(int seconds) { mUserAuthenticationValidityDurationSeconds = seconds; @@ -473,27 +473,15 @@ public final class KeyStoreParameter implements ProtectionParameter { } /** - * Sets whether this key must be invalidated (permanently) whenever a new fingerprint is - * enrolled. This only has effect if fingerprint reader is one of the user authenticators - * protecting access to the key. - * - * <p>By default, enrolling a new fingerprint does not invalidate the key. - * - * @see #setUserAuthenticators(Set) - */ - public Builder setInvalidatedOnNewFingerprintEnrolled(boolean invalidated) { - mInvalidatedOnNewFingerprintEnrolled = invalidated; - return this; - } - - /** * Builds the instance of the {@code KeyStoreParameter}. * * @throws IllegalArgumentException if a required field is missing * @return built instance of {@code KeyStoreParameter} */ public KeyStoreParameter build() { - return new KeyStoreParameter(mFlags, + return new KeyStoreParameter( + mContext, + mFlags, mKeyValidityStart, mKeyValidityForOriginationEnd, mKeyValidityForConsumptionEnd, @@ -503,9 +491,8 @@ public final class KeyStoreParameter implements ProtectionParameter { mDigests, mBlockModes, mRandomizedEncryptionRequired, - mUserAuthenticators, - mUserAuthenticationValidityDurationSeconds, - mInvalidatedOnNewFingerprintEnrolled); + mUserAuthenticationRequired, + mUserAuthenticationValidityDurationSeconds); } } } diff --git a/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java index 4be0638ca1a1..bfe09e3e1b73 100644 --- a/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java +++ b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java @@ -81,8 +81,8 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { String[] encryptionPaddings; String[] digests; String[] blockModes; - @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators; - @KeyStoreKeyProperties.UserAuthenticatorEnum int teeEnforcedUserAuthenticators; + int keymasterSwEnforcedUserAuthenticators; + int keymasterHwEnforcedUserAuthenticators; try { if (keyCharacteristics.hwEnforced.containsTag(KeymasterDefs.KM_TAG_ORIGIN)) { teeBacked = true; @@ -122,21 +122,10 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { keyCharacteristics.getInts(KeymasterDefs.KM_TAG_DIGEST)); blockModes = KeymasterUtils.getJcaBlockModesFromKeymasterBlockModes( keyCharacteristics.getInts(KeymasterDefs.KM_TAG_BLOCK_MODE)); - - @KeyStoreKeyProperties.UserAuthenticatorEnum - int swEnforcedKeymasterUserAuthenticators = + keymasterSwEnforcedUserAuthenticators = keyCharacteristics.swEnforced.getInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0); - @KeyStoreKeyProperties.UserAuthenticatorEnum - int hwEnforcedKeymasterUserAuthenticators = + keymasterHwEnforcedUserAuthenticators = keyCharacteristics.hwEnforced.getInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0); - @KeyStoreKeyProperties.UserAuthenticatorEnum - int keymasterUserAuthenticators = - swEnforcedKeymasterUserAuthenticators | hwEnforcedKeymasterUserAuthenticators; - userAuthenticators = KeyStoreKeyProperties.UserAuthenticator.allFromKeymaster( - keymasterUserAuthenticators); - teeEnforcedUserAuthenticators = - KeyStoreKeyProperties.UserAuthenticator.allFromKeymaster( - hwEnforcedKeymasterUserAuthenticators); } catch (IllegalArgumentException e) { throw new InvalidKeySpecException("Unsupported key characteristic", e); } @@ -157,11 +146,13 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { && (keyValidityForConsumptionEnd.getTime() == Long.MAX_VALUE)) { keyValidityForConsumptionEnd = null; } + boolean userAuthenticationRequired = + !keyCharacteristics.getBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED); int userAuthenticationValidityDurationSeconds = keyCharacteristics.getInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, -1); - - // TODO: Populate the value below from key characteristics once Keymaster is ready. - boolean invalidatedOnNewFingerprintEnrolled = false; + boolean userAuthenticationRequirementEnforcedInTee = (userAuthenticationRequired) + && (keymasterHwEnforcedUserAuthenticators != 0) + && (keymasterSwEnforcedUserAuthenticators == 0); return new KeyStoreKeySpec(entryAlias, teeBacked, @@ -175,10 +166,9 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { EmptyArray.STRING, // no signature paddings -- this is symmetric crypto digests, blockModes, - userAuthenticators, - teeEnforcedUserAuthenticators, + userAuthenticationRequired, userAuthenticationValidityDurationSeconds, - invalidatedOnNewFingerprintEnrolled); + userAuthenticationRequirementEnforcedInTee); } @Override diff --git a/keystore/java/android/security/KeymasterUtils.java b/keystore/java/android/security/KeymasterUtils.java index 67f75c26b451..7bf5475ab16d 100644 --- a/keystore/java/android/security/KeymasterUtils.java +++ b/keystore/java/android/security/KeymasterUtils.java @@ -16,7 +16,14 @@ package android.security; +import android.content.Context; +import android.hardware.fingerprint.FingerprintManager; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.UserHandle; +import android.security.keymaster.KeymasterArguments; import android.security.keymaster.KeymasterDefs; +import android.service.gatekeeper.IGateKeeperService; import libcore.util.EmptyArray; @@ -339,4 +346,72 @@ public abstract class KeymasterUtils { } return result; } + + private static long getRootSid() { + IGateKeeperService gatekeeperService = IGateKeeperService.Stub.asInterface( + ServiceManager.getService("android.service.gatekeeper.IGateKeeperService")); + if (gatekeeperService == null) { + throw new IllegalStateException("Gatekeeper service not available"); + } + + try { + return gatekeeperService.getSecureUserId(UserHandle.myUserId()); + } catch (RemoteException e) { + throw new IllegalStateException("Failed to obtain root SID"); + } + } + + /** + * Adds keymaster arguments to express the key's authorization policy supported by user + * authentication. + * + * @param userAuthenticationRequired whether user authentication is required to authorize the + * use of the key. + * @param userAuthenticationValidityDurationSeconds duration of time (seconds) for which user + * authentication is valid as authorization for using the key or {@code -1} if every + * use of the key needs authorization. + */ + public static void addUserAuthArgs(KeymasterArguments args, + Context context, + boolean userAuthenticationRequired, + int userAuthenticationValidityDurationSeconds) { + if (!userAuthenticationRequired) { + args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED); + return; + } + + if (userAuthenticationValidityDurationSeconds == -1) { + // Every use of this key needs to be authorized by the user. This currently means + // fingerprint-only auth. + FingerprintManager fingerprintManager = + context.getSystemService(FingerprintManager.class); + if ((fingerprintManager == null) || (!fingerprintManager.isHardwareDetected())) { + throw new IllegalStateException( + "This device does not support keys which require authentication for every" + + " use -- this requires fingerprint authentication which is not" + + " available on this device"); + } + long fingerprintOnlySid = fingerprintManager.getAuthenticatorId(); + if (fingerprintOnlySid == 0) { + throw new IllegalStateException( + "At least one fingerprint must be enrolled to create keys requiring user" + + " authentication for every use"); + } + args.addLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, fingerprintOnlySid); + args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT); + } 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. + long rootSid = getRootSid(); + if (rootSid == 0) { + throw new IllegalStateException("Secure lock screen must be enabled" + + " to create keys requiring user authentication"); + } + args.addLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, rootSid); + args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, + KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_FINGERPRINT); + args.addInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, + userAuthenticationValidityDurationSeconds); + } + } } diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h index 65daf03157f4..c8189b8df955 100644 --- a/libs/hwui/FrameInfo.h +++ b/libs/hwui/FrameInfo.h @@ -53,6 +53,7 @@ enum class FrameInfoFlags { kWindowLayoutChanged = 1 << 0, kRTAnimation = 1 << 1, kSurfaceCanvas = 1 << 2, + kSkippedFrame = 1 << 3, }; MAKE_FLAGS_ENUM(FrameInfoFlags) @@ -101,6 +102,10 @@ public: set(FrameInfoIndex::kFrameCompleted) = systemTime(CLOCK_MONOTONIC); } + void addFlag(FrameInfoFlags flag) { + set(FrameInfoIndex::kFlags) |= static_cast<uint64_t>(flag); + } + int64_t operator[](FrameInfoIndex index) const { if (index == FrameInfoIndex::kNumIndexes) return 0; return mFrameInfo[static_cast<int>(index)]; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 30935d53fc0f..f1ec8ae0c167 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1262,7 +1262,7 @@ void OpenGLRenderer::attachStencilBufferToLayer(Layer* layer) { endTiling(); RenderBuffer* buffer = mCaches.renderBufferCache.get( - Stencil::getSmallestStencilFormat(), + Stencil::getLayerStencilFormat(), layer->getWidth(), layer->getHeight()); layer->setStencilRenderBuffer(buffer); diff --git a/libs/hwui/renderstate/Stencil.cpp b/libs/hwui/renderstate/Stencil.cpp index cedb23341e1d..92a057d92c5d 100644 --- a/libs/hwui/renderstate/Stencil.cpp +++ b/libs/hwui/renderstate/Stencil.cpp @@ -42,12 +42,17 @@ uint8_t Stencil::getStencilSize() { return STENCIL_BUFFER_SIZE; } -GLenum Stencil::getSmallestStencilFormat() { +/** + * This method will return either GL_STENCIL_INDEX4_OES if supported, + * GL_STENCIL_INDEX8 if not. + * + * Layers can't use a single bit stencil because multi-rect ClipArea needs a high enough + * stencil resolution to represent the summation of multiple intersecting rect geometries. + */ +GLenum Stencil::getLayerStencilFormat() { #if !DEBUG_STENCIL const Extensions& extensions = Caches::getInstance().extensions(); - if (extensions.has1BitStencil()) { - return GL_STENCIL_INDEX1_OES; - } else if (extensions.has4BitStencil()) { + if (extensions.has4BitStencil()) { return GL_STENCIL_INDEX4_OES; } #endif diff --git a/libs/hwui/renderstate/Stencil.h b/libs/hwui/renderstate/Stencil.h index e4f0f3f07ac6..3a8f8ebad48d 100644 --- a/libs/hwui/renderstate/Stencil.h +++ b/libs/hwui/renderstate/Stencil.h @@ -42,10 +42,7 @@ public: */ ANDROID_API static uint8_t getStencilSize(); - /** - * Returns the smallest stencil format accepted by render buffers. - */ - static GLenum getSmallestStencilFormat(); + static GLenum getLayerStencilFormat(); /** * Clears the stencil buffer. diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 92371514f540..3de3086a2f86 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -27,12 +27,25 @@ #include "../OpenGLRenderer.h" #include <algorithm> +#include <cutils/properties.h> #include <private/hwui/DrawGlInfo.h> #include <strings.h> #define TRIM_MEMORY_COMPLETE 80 #define TRIM_MEMORY_UI_HIDDEN 20 +#define PROPERTY_SKIP_EMPTY_DAMAGE "debug.hwui.skip_empty_damage" + +static bool sInitialized = false; +static bool sSkipEmptyDamage = true; + +static void initGlobals() { + if (sInitialized) return; + sInitialized = true; + sSkipEmptyDamage = property_get_bool(PROPERTY_SKIP_EMPTY_DAMAGE, + sSkipEmptyDamage); +} + namespace android { namespace uirenderer { namespace renderthread { @@ -45,6 +58,9 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, , mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord())) , mRootRenderNode(rootRenderNode) , mJankTracker(thread.timeLord().frameIntervalNanos()) { + // Done lazily at first draw instead of at library load to avoid + // running pre-zygote fork + initGlobals(); mRenderThread.renderState().registerCanvasContext(this); mProfiler.setDensity(mRenderThread.mainDisplayInfo().density); } @@ -203,12 +219,17 @@ void CanvasContext::draw() { LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE, "drawRenderNode called on a context with no canvas or surface!"); - profiler().markPlaybackStart(); - mCurrentFrameInfo->markIssueDrawCommandsStart(); - SkRect dirty; mDamageAccumulator.finish(&dirty); + if (dirty.isEmpty() && sSkipEmptyDamage) { + mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame); + return; + } + + profiler().markPlaybackStart(); + mCurrentFrameInfo->markIssueDrawCommandsStart(); + EGLint width, height; mEglManager.beginFrame(mEglSurface, &width, &height); if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) { @@ -277,6 +298,8 @@ void CanvasContext::doFrame() { prepareTree(info, frameInfo); if (info.out.canDrawThisFrame) { draw(); + } else { + mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame); } } diff --git a/location/java/android/location/GpsMeasurement.java b/location/java/android/location/GpsMeasurement.java index df128c919798..f13a440f411a 100644 --- a/location/java/android/location/GpsMeasurement.java +++ b/location/java/android/location/GpsMeasurement.java @@ -140,8 +140,6 @@ public class GpsMeasurement implements Parcelable { /** * The state of the GPS receiver contains millisecond ambiguity. - * - * @hide */ public static final short STATE_MSEC_AMBIGUOUS = (1<<4); @@ -399,8 +397,6 @@ public class GpsMeasurement implements Parcelable { * * @return {@code true} if {@link #getPseudorangeRateInMetersPerSec()} contains a corrected * value, {@code false} if it contains an uncorrected value. - * - * @hide */ public boolean isPseudorangeRateCorrected() { return !isFlagSet(GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE); diff --git a/location/java/android/location/GpsNavigationMessage.java b/location/java/android/location/GpsNavigationMessage.java index 5b12a61a2c36..5c3c71012cdd 100644 --- a/location/java/android/location/GpsNavigationMessage.java +++ b/location/java/android/location/GpsNavigationMessage.java @@ -62,23 +62,17 @@ public class GpsNavigationMessage implements Parcelable { /** * The Navigation Message Status is 'unknown'. - * - * @hide */ public static final short STATUS_UNKNOWN = 0; /** * The Navigation Message was received without any parity error in its navigation words. - * - * @hide */ public static final short STATUS_PARITY_PASSED = (1<<0); /** * The Navigation Message was received with words that failed parity check, but the receiver was * able to correct those words. - * - * @hide */ public static final short STATUS_PARITY_REBUILT = (1<<1); @@ -220,8 +214,6 @@ public class GpsNavigationMessage implements Parcelable { /** * Gets the Status of the navigation message contained in the object. - * - * @hide */ public short getStatus() { return mStatus; @@ -229,8 +221,6 @@ public class GpsNavigationMessage implements Parcelable { /** * Sets the status of the navigation message. - * - * @hide */ public void setStatus(short value) { mStatus = value; diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java index abb4257668b9..a7219231b5e5 100644 --- a/media/java/android/media/AudioManagerInternal.java +++ b/media/java/android/media/AudioManagerInternal.java @@ -51,5 +51,7 @@ public abstract class AudioManagerInternal { /** Called when internal ringer mode is evaluated, returns the new external ringer mode */ int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller, int ringerModeExternal, VolumePolicy policy); + + boolean canVolumeDownEnterSilent(); } } diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 201a7962db0e..d5e6b3eea6f0 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -26,6 +26,8 @@ import java.util.Iterator; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.app.ActivityThread; +import android.app.Application; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -378,7 +380,7 @@ public class AudioRecord int initResult = native_setup( new WeakReference<AudioRecord>(this), mAudioAttributes, mSampleRate, mChannelMask, mChannelIndexMask, mAudioFormat, mNativeBufferSizeInBytes, - session); + session, getMyOpPackageName()); if (initResult != SUCCESS) { loge("Error code "+initResult+" when initializing native AudioRecord object."); return; // with mState == STATE_UNINITIALIZED @@ -1321,7 +1323,6 @@ public class AudioRecord return native_set_pos_update_period(periodInFrames); } - //-------------------------------------------------------------------------- // Explicit Routing //-------------------- @@ -1451,7 +1452,7 @@ public class AudioRecord private native final int native_setup(Object audiorecord_this, Object /*AudioAttributes*/ attributes, int sampleRate, int channelMask, int channelIndexMask, int audioFormat, - int buffSizeInBytes, int[] sessionId); + int buffSizeInBytes, int[] sessionId, String opPackageName); // TODO remove: implementation calls directly into implementation of native_release() private native final void native_finalize(); @@ -1500,4 +1501,14 @@ public class AudioRecord Log.e(TAG, msg); } + private static String getMyOpPackageName() { + ActivityThread activityThread = ActivityThread.currentActivityThread(); + if (activityThread != null) { + Application application = activityThread.getApplication(); + if (application != null) { + return application.getOpPackageName(); + } + } + throw new IllegalStateException("Cannot create AudioRecord outside of an app"); + } } diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 78fd9f032620..1b054cc55525 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -18,6 +18,7 @@ package android.media; import android.annotation.SystemApi; import android.app.ActivityThread; +import android.app.Application; import android.hardware.Camera; import android.os.Handler; import android.os.Looper; @@ -111,7 +112,7 @@ public class MediaRecorder /* Native setup requires a weak reference to our object. * It's easier to create it here than in C++. */ - native_setup(new WeakReference<MediaRecorder>(this), packageName); + native_setup(new WeakReference<MediaRecorder>(this), packageName, getMyOpPackageName()); } /** @@ -1080,7 +1081,7 @@ public class MediaRecorder private static native final void native_init(); private native final void native_setup(Object mediarecorder_this, - String clientName) throws IllegalStateException; + String clientName, String opPackageName) throws IllegalStateException; private native final void native_finalize(); @@ -1088,4 +1089,15 @@ public class MediaRecorder @Override protected void finalize() { native_finalize(); } + + private static String getMyOpPackageName() { + ActivityThread activityThread = ActivityThread.currentActivityThread(); + if (activityThread != null) { + Application application = activityThread.getApplication(); + if (application != null) { + return application.getOpPackageName(); + } + } + throw new IllegalStateException("Cannot create AudioRecord outside of an app"); + } } diff --git a/media/java/android/media/RemoteDisplay.java b/media/java/android/media/RemoteDisplay.java index 4e937a5dc459..5add65a93bcb 100644 --- a/media/java/android/media/RemoteDisplay.java +++ b/media/java/android/media/RemoteDisplay.java @@ -37,17 +37,19 @@ public final class RemoteDisplay { private final CloseGuard mGuard = CloseGuard.get(); private final Listener mListener; private final Handler mHandler; + private final String mOpPackageName; private long mPtr; - private native long nativeListen(String iface); + private native long nativeListen(String iface, String opPackageName); private native void nativeDispose(long ptr); private native void nativePause(long ptr); private native void nativeResume(long ptr); - private RemoteDisplay(Listener listener, Handler handler) { + private RemoteDisplay(Listener listener, Handler handler, String opPackageName) { mListener = listener; mHandler = handler; + mOpPackageName = opPackageName; } @Override @@ -66,7 +68,8 @@ public final class RemoteDisplay { * @param listener The listener to invoke when displays are connected or disconnected. * @param handler The handler on which to invoke the listener. */ - public static RemoteDisplay listen(String iface, Listener listener, Handler handler) { + public static RemoteDisplay listen(String iface, Listener listener, Handler handler, + String opPackageName) { if (iface == null) { throw new IllegalArgumentException("iface must not be null"); } @@ -77,7 +80,7 @@ public final class RemoteDisplay { throw new IllegalArgumentException("handler must not be null"); } - RemoteDisplay display = new RemoteDisplay(listener, handler); + RemoteDisplay display = new RemoteDisplay(listener, handler, opPackageName); display.startListening(iface); return display; } @@ -113,7 +116,7 @@ public final class RemoteDisplay { } private void startListening(String iface) { - mPtr = nativeListen(iface); + mPtr = nativeListen(iface, mOpPackageName); if (mPtr == 0) { throw new IllegalStateException("Could not start listening for " + "remote display connection on \"" + iface + "\""); diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java index a8b9686e8df9..9fc90dfad293 100644 --- a/media/java/android/media/audiofx/AudioEffect.java +++ b/media/java/android/media/audiofx/AudioEffect.java @@ -18,6 +18,8 @@ package android.media.audiofx; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.app.ActivityThread; +import android.app.Application; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -395,7 +397,7 @@ public class AudioEffect { // native initialization int initResult = native_setup(new WeakReference<AudioEffect>(this), type.toString(), uuid.toString(), priority, audioSession, id, - desc); + desc, getMyOpPackageName()); if (initResult != SUCCESS && initResult != ALREADY_EXISTS) { Log.e(TAG, "Error code " + initResult + " when initializing AudioEffect."); @@ -1217,7 +1219,8 @@ public class AudioEffect { private static native final void native_init(); private native final int native_setup(Object audioeffect_this, String type, - String uuid, int priority, int audioSession, int[] id, Object[] desc); + String uuid, int priority, int audioSession, int[] id, Object[] desc, + String opPackageName); private native final void native_finalize(); @@ -1356,4 +1359,15 @@ public class AudioEffect { } return b; } + + private static String getMyOpPackageName() { + ActivityThread activityThread = ActivityThread.currentActivityThread(); + if (activityThread != null) { + Application application = activityThread.getApplication(); + if (application != null) { + return application.getOpPackageName(); + } + } + throw new IllegalStateException("Cannot create AudioEffect outside of an app"); + } } diff --git a/media/java/android/media/audiofx/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java index 24c74ac4be78..0c48063f394a 100644 --- a/media/java/android/media/audiofx/Visualizer.java +++ b/media/java/android/media/audiofx/Visualizer.java @@ -16,6 +16,8 @@ package android.media.audiofx; +import android.app.ActivityThread; +import android.app.Application; import android.util.Log; import java.lang.ref.WeakReference; import android.os.Handler; @@ -206,7 +208,8 @@ public class Visualizer { synchronized (mStateLock) { mState = STATE_UNINITIALIZED; // native initialization - int result = native_setup(new WeakReference<Visualizer>(this), audioSession, id); + int result = native_setup(new WeakReference<Visualizer>(this), audioSession, id, + getMyOpPackageName()); if (result != SUCCESS && result != ALREADY_EXISTS) { Log.e(TAG, "Error code "+result+" when initializing Visualizer."); switch (result) { @@ -716,7 +719,8 @@ public class Visualizer { private native final int native_setup(Object audioeffect_this, int audioSession, - int[] id); + int[] id, + String opPackageName); private native final void native_finalize(); @@ -766,5 +770,15 @@ public class Visualizer { } + private static String getMyOpPackageName() { + ActivityThread activityThread = ActivityThread.currentActivityThread(); + if (activityThread != null) { + Application application = activityThread.getApplication(); + if (application != null) { + return application.getOpPackageName(); + } + } + throw new IllegalStateException("Cannot create AudioRecord outside of an app"); + } } diff --git a/media/java/android/media/midi/MidiDeviceInfo.java b/media/java/android/media/midi/MidiDeviceInfo.java index af108eb308e6..35374ed133ca 100644 --- a/media/java/android/media/midi/MidiDeviceInfo.java +++ b/media/java/android/media/midi/MidiDeviceInfo.java @@ -69,6 +69,13 @@ public final class MidiDeviceInfo implements Parcelable { public static final String PROPERTY_PRODUCT = "product"; /** + * Bundle key for the device's version property. + * Used with the {@link android.os.Bundle} returned by {@link #getProperties} + * Matches the USB device version number for USB MIDI devices. + */ + public static final String PROPERTY_VERSION = "version"; + + /** * Bundle key for the device's serial number property. * Used with the {@link android.os.Bundle} returned by {@link #getProperties} * Matches the USB device serial number for USB MIDI devices. diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java index a3442e36e66e..95aaa7f4e24c 100644 --- a/media/java/android/media/tv/ITvInputSessionWrapper.java +++ b/media/java/android/media/tv/ITvInputSessionWrapper.java @@ -41,8 +41,9 @@ import com.android.internal.os.SomeArgs; public class ITvInputSessionWrapper extends ITvInputSession.Stub implements HandlerCaller.Callback { private static final String TAG = "TvInputSessionWrapper"; - private static final int MESSAGE_HANDLING_DURATION_THRESHOLD_MILLIS = 50; - private static final int MESSAGE_TUNE_DURATION_THRESHOLD_MILLIS = 2000; + private static final int EXECUTE_MESSAGE_TIMEOUT_SHORT_MILLIS = 50; + private static final int EXECUTE_MESSAGE_TUNE_TIMEOUT_MILLIS = 2000; + private static final int EXECUTE_MESSAGE_TIMEOUT_LONG_MILLIS = 5 * 1000; private static final int DO_RELEASE = 1; private static final int DO_SET_MAIN = 2; @@ -184,14 +185,18 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand } } long duration = System.currentTimeMillis() - startTime; - if (duration > MESSAGE_HANDLING_DURATION_THRESHOLD_MILLIS) { + if (duration > EXECUTE_MESSAGE_TIMEOUT_SHORT_MILLIS) { Log.w(TAG, "Handling message (" + msg.what + ") took too long time (duration=" + duration + "ms)"); - if (msg.what == DO_TUNE && duration > MESSAGE_TUNE_DURATION_THRESHOLD_MILLIS) { + if (msg.what == DO_TUNE && duration > EXECUTE_MESSAGE_TUNE_TIMEOUT_MILLIS) { throw new RuntimeException("Too much time to handle tune request. (" + duration - + "ms > " + MESSAGE_TUNE_DURATION_THRESHOLD_MILLIS + "ms) " + + "ms > " + EXECUTE_MESSAGE_TUNE_TIMEOUT_MILLIS + "ms) " + "Consider handling the tune request in a separate thread."); } + if (duration > EXECUTE_MESSAGE_TIMEOUT_LONG_MILLIS) { + throw new RuntimeException("Too much time to handle a request. (type=" + msg.what + + ", " + duration + "ms > " + EXECUTE_MESSAGE_TIMEOUT_LONG_MILLIS + "ms)."); + } } } diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp index 8b7d40d03ed1..02297fc7ba74 100644 --- a/media/jni/android_media_MediaRecorder.cpp +++ b/media/jni/android_media_MediaRecorder.cpp @@ -31,6 +31,8 @@ #include <media/mediarecorder.h> #include <utils/threads.h> +#include <ScopedUtfChars.h> + #include "jni.h" #include "JNIHelp.h" #include "android_runtime/AndroidRuntime.h" @@ -444,11 +446,13 @@ android_media_MediaRecorder_native_init(JNIEnv *env) static void android_media_MediaRecorder_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, - jstring packageName) + jstring packageName, jstring opPackageName) { ALOGV("setup"); - sp<MediaRecorder> mr = new MediaRecorder(); + ScopedUtfChars opPackageNameStr(env, opPackageName); + + sp<MediaRecorder> mr = new MediaRecorder(String16(opPackageNameStr.c_str())); if (mr == NULL) { jniThrowException(env, "java/lang/RuntimeException", "Out of memory"); return; @@ -506,7 +510,8 @@ static JNINativeMethod gMethods[] = { {"native_reset", "()V", (void *)android_media_MediaRecorder_native_reset}, {"release", "()V", (void *)android_media_MediaRecorder_release}, {"native_init", "()V", (void *)android_media_MediaRecorder_native_init}, - {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;)V", (void *)android_media_MediaRecorder_native_setup}, + {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V", + (void *)android_media_MediaRecorder_native_setup}, {"native_finalize", "()V", (void *)android_media_MediaRecorder_native_finalize}, }; diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp index c364d4693c88..96b72a2a5ccf 100644 --- a/media/jni/audioeffect/android_media_AudioEffect.cpp +++ b/media/jni/audioeffect/android_media_AudioEffect.cpp @@ -25,6 +25,8 @@ #include <android_runtime/AndroidRuntime.h> #include "media/AudioEffect.h" +#include <ScopedUtfChars.h> + using namespace android; #define AUDIOEFFECT_SUCCESS 0 @@ -249,7 +251,8 @@ android_media_AudioEffect_native_init(JNIEnv *env) static jint android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, - jstring type, jstring uuid, jint priority, jint sessionId, jintArray jId, jobjectArray javadesc) + jstring type, jstring uuid, jint priority, jint sessionId, jintArray jId, + jobjectArray javadesc, jstring opPackageName) { ALOGV("android_media_AudioEffect_native_setup"); AudioEffectJniStorage* lpJniStorage = NULL; @@ -267,6 +270,8 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t jstring jdescName; jstring jdescImplementor; + ScopedUtfChars opPackageNameStr(env, opPackageName); + if (type != NULL) { typeStr = env->GetStringUTFChars(type, NULL); if (typeStr == NULL) { // Out of memory @@ -312,6 +317,7 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t // create the native AudioEffect object lpAudioEffect = new AudioEffect(typeStr, + String16(opPackageNameStr.c_str()), uuidStr, priority, effectCallback, @@ -868,7 +874,7 @@ android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz _ // Dalvik VM type signatures static JNINativeMethod gMethods[] = { {"native_init", "()V", (void *)android_media_AudioEffect_native_init}, - {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;II[I[Ljava/lang/Object;)I", + {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;II[I[Ljava/lang/Object;Ljava/lang/String;)I", (void *)android_media_AudioEffect_native_setup}, {"native_finalize", "()V", (void *)android_media_AudioEffect_native_finalize}, {"native_release", "()V", (void *)android_media_AudioEffect_native_release}, diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp index 460277fe6766..abc681e89201 100644 --- a/media/jni/audioeffect/android_media_Visualizer.cpp +++ b/media/jni/audioeffect/android_media_Visualizer.cpp @@ -26,6 +26,8 @@ #include <utils/threads.h> #include "media/Visualizer.h" +#include <ScopedUtfChars.h> + using namespace android; #define VISUALIZER_SUCCESS 0 @@ -331,7 +333,7 @@ static void android_media_visualizer_effect_callback(int32_t event, static jint android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, - jint sessionId, jintArray jId) + jint sessionId, jintArray jId, jstring opPackageName) { ALOGV("android_media_visualizer_native_setup"); visualizerJniStorage* lpJniStorage = NULL; @@ -339,6 +341,8 @@ android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_th Visualizer* lpVisualizer = NULL; jint* nId = NULL; + ScopedUtfChars opPackageNameStr(env, opPackageName); + lpJniStorage = new visualizerJniStorage(); if (lpJniStorage == NULL) { ALOGE("setup: Error creating JNI Storage"); @@ -362,7 +366,8 @@ android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_th } // create the native Visualizer object - lpVisualizer = new Visualizer(0, + lpVisualizer = new Visualizer(String16(opPackageNameStr.c_str()), + 0, android_media_visualizer_effect_callback, lpJniStorage, sessionId); @@ -662,7 +667,7 @@ android_media_setPeriodicCapture(JNIEnv *env, jobject thiz, jint rate, jboolean // Dalvik VM type signatures static JNINativeMethod gMethods[] = { {"native_init", "()V", (void *)android_media_visualizer_native_init}, - {"native_setup", "(Ljava/lang/Object;I[I)I", + {"native_setup", "(Ljava/lang/Object;I[ILjava/lang/String;)I", (void *)android_media_visualizer_native_setup}, {"native_finalize", "()V", (void *)android_media_visualizer_native_finalize}, {"native_release", "()V", (void *)android_media_visualizer_native_release}, diff --git a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml index dc7c94553749..d2a642476964 100644 --- a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml +++ b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml @@ -71,5 +71,5 @@ </plurals> <string name="notification_touch_for_details" msgid="4483108577842961665">"Толығырақ мәліметті көру үшін түртіңіз"</string> <string name="retry" msgid="7564024179122207376">"Қайталау"</string> - <string name="copy_failure_alert_content" msgid="3715575000297709082">"Бұл файлдар көшірілмейді: <xliff:g id="LIST">%1$s</xliff:g>"</string> + <string name="copy_failure_alert_content" msgid="3715575000297709082">"Мына файлдар көшірілген жоқ: <xliff:g id="LIST">%1$s</xliff:g>"</string> </resources> diff --git a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml index f7c6c4565cb5..1b15b9f91433 100644 --- a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml +++ b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml @@ -66,8 +66,8 @@ </plurals> <string name="copy_preparing" msgid="3896202461003039386">"Nuxsa olishga tayyorgarlik..."</string> <plurals name="copy_error_notification_title" formatted="false" msgid="5267616889076217261"> - <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> ta fayldan nusxa olinmadi</item> - <item quantity="one"> <xliff:g id="COUNT_0">%1$d</xliff:g> ta fayldan nusxa olinmadi</item> + <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ta fayldan nusxa olinmadi</item> + <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta fayldan nusxa olinmadi</item> </plurals> <string name="notification_touch_for_details" msgid="4483108577842961665">"Batafsil ma’lumot olish uchun bosing"</string> <string name="retry" msgid="7564024179122207376">"Qayta urinish"</string> diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml index 744ace1809c7..96e3e3dddfdf 100644 --- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml +++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml @@ -65,9 +65,11 @@ <item quantity="one">正在复制 <xliff:g id="COUNT_0">%1$d</xliff:g> 个文件。</item> </plurals> <string name="copy_preparing" msgid="3896202461003039386">"正在准备复制…"</string> - <!-- no translation found for copy_error_notification_title (5267616889076217261) --> + <plurals name="copy_error_notification_title" formatted="false" msgid="5267616889076217261"> + <item quantity="other">无法复制 <xliff:g id="COUNT_1">%1$d</xliff:g> 个文件</item> + <item quantity="one">无法复制 <xliff:g id="COUNT_0">%1$d</xliff:g> 个文件</item> + </plurals> <string name="notification_touch_for_details" msgid="4483108577842961665">"触摸可查看详情"</string> <string name="retry" msgid="7564024179122207376">"重试"</string> - <!-- no translation found for copy_failure_alert_content (3715575000297709082) --> - <skip /> + <string name="copy_failure_alert_content" msgid="3715575000297709082">"以下文件无法复制:<xliff:g id="LIST">%1$s</xliff:g>"</string> </resources> diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml index 352ba9e87a34..1fa402eacd19 100644 --- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml +++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml @@ -71,5 +71,5 @@ </plurals> <string name="notification_touch_for_details" msgid="4483108577842961665">"輕觸即可查看詳情"</string> <string name="retry" msgid="7564024179122207376">"重試"</string> - <string name="copy_failure_alert_content" msgid="3715575000297709082">"以下檔案不會被複製:<xliff:g id="LIST">%1$s</xliff:g>"</string> + <string name="copy_failure_alert_content" msgid="3715575000297709082">"以下檔案未能複製:<xliff:g id="LIST">%1$s</xliff:g>"</string> </resources> diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java index e5cca2342d33..b8d9053093d1 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -679,7 +679,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { cb.onScreenTurnedOn(); } } - startListeningForFingerprint(); + updateFingerprintListeningState(); } protected void handleScreenTurnedOff(int arg1) { @@ -691,7 +691,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { cb.onScreenTurnedOff(arg1); } } - stopListeningForFingerprint(); + updateFingerprintListeningState(); } /** @@ -764,14 +764,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0, reply)); mSwitchingUser = true; - stopListeningForFingerprint(); + updateFingerprintListeningState(); } @Override public void onUserSwitchComplete(int newUserId) throws RemoteException { mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE, newUserId, 0)); mSwitchingUser = false; - startListeningForFingerprint(); + updateFingerprintListeningState(); } @Override public void onForegroundProfileSwitch(int newProfileId) { @@ -787,7 +787,20 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { trustManager.registerTrustListener(this); mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE); - startListeningForFingerprint(); + updateFingerprintListeningState(); + } + + private void updateFingerprintListeningState() { + boolean shouldListenForFingerprint = shouldListenForFingerprint(); + if (mFingerprintDetectionRunning && !shouldListenForFingerprint) { + stopListeningForFingerprint(); + } else if (!mFingerprintDetectionRunning && shouldListenForFingerprint) { + startListeningForFingerprint(); + } + } + + private boolean shouldListenForFingerprint() { + return mScreenOn && mKeyguardIsVisible && !mSwitchingUser; } private void startListeningForFingerprint() { @@ -804,7 +817,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } - public void stopListeningForFingerprint() { + private void stopListeningForFingerprint() { if (DEBUG) Log.v(TAG, "stopListeningForFingerprint()"); if (isFingerprintDetectionRunning()) { mFingerprintCancelSignal.cancel(); @@ -1062,6 +1075,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { cb.onKeyguardVisibilityChangedRaw(isShowing); } } + updateFingerprintListeningState(); } /** diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_fingerprint_ridges_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_fingerprint_ridges_animation.xml new file mode 100644 index 000000000000..c6a462255844 --- /dev/null +++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_fingerprint_ridges_animation.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="100" + android:propertyName="rotation" + android:valueFrom="0.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="566" + android:propertyName="rotation" + android:valueFrom="0.0" + android:valueTo="-305.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_3" /> + <objectAnimator + android:duration="1066" + android:propertyName="rotation" + android:valueFrom="-305.0" + android:valueTo="-305.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0" /> + <objectAnimator + android:duration="800" + android:propertyName="rotation" + android:valueFrom="-305.0" + android:valueTo="-720.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0" /> + </set> +</set> diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_group_1_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_group_1_animation.xml new file mode 100644 index 000000000000..0e2c2f008cb9 --- /dev/null +++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_group_1_animation.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="183" + android:propertyName="rotation" + android:valueFrom="285.0" + android:valueTo="285.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="516" + android:propertyName="rotation" + android:valueFrom="285.0" + android:valueTo="90.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_1" /> + </set> +</set> diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_group_2_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_group_2_animation.xml new file mode 100644 index 000000000000..c01010d315fc --- /dev/null +++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_group_2_animation.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="283" + android:propertyName="scaleX" + android:valueFrom="0.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="316" + android:propertyName="scaleX" + android:valueFrom="0.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_1" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="283" + android:propertyName="scaleY" + android:valueFrom="0.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="316" + android:propertyName="scaleY" + android:valueFrom="0.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_1" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="283" + android:propertyName="rotation" + android:valueFrom="184.0" + android:valueTo="184.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="316" + android:propertyName="rotation" + android:valueFrom="184.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_1" /> + </set> +</set> diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_path_3_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_path_3_animation.xml new file mode 100644 index 000000000000..454be2455aaf --- /dev/null +++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_path_3_animation.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="233" + android:propertyName="trimPathStart" + android:valueFrom="1.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="466" + android:propertyName="trimPathStart" + android:valueFrom="1.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_1_path_0_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_1_path_0_animation.xml new file mode 100644 index 000000000000..faeecf4c825a --- /dev/null +++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_1_path_0_animation.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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" > + <objectAnimator + android:duration="133" + android:propertyName="trimPathEnd" + android:valueFrom="0.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="100" + android:propertyName="trimPathStart" + android:valueFrom="0.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="100" + android:propertyName="trimPathStart" + android:valueFrom="0.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_2" /> + </set> +</set> diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_1_path_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_1_path_animation.xml new file mode 100644 index 000000000000..3bacf033739b --- /dev/null +++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_1_path_animation.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="16" + android:propertyName="trimPathStart" + android:valueFrom="0.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="66" + android:propertyName="trimPathStart" + android:valueFrom="0.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + </set> +</set> diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_2_path_0_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_2_path_0_animation.xml new file mode 100644 index 000000000000..80a0faaa08ad --- /dev/null +++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_2_path_0_animation.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="116" + android:propertyName="trimPathEnd" + android:valueFrom="1.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="116" + android:propertyName="trimPathEnd" + android:valueFrom="1.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_3" /> + </set> + <objectAnimator + android:duration="166" + android:propertyName="trimPathStart" + android:valueFrom="1.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_3" /> +</set> diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_2_path_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_2_path_animation.xml new file mode 100644 index 000000000000..3a182968775e --- /dev/null +++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_2_path_animation.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="16" + android:propertyName="trimPathEnd" + android:valueFrom="1.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="133" + android:propertyName="trimPathEnd" + android:valueFrom="1.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + </set> +</set> diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_5_path_0_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_5_path_0_animation.xml new file mode 100644 index 000000000000..1e16df7c2ad3 --- /dev/null +++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_5_path_0_animation.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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" > + <objectAnimator + android:duration="166" + android:propertyName="trimPathEnd" + android:valueFrom="0.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="150" + android:propertyName="trimPathStart" + android:valueFrom="0.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="166" + android:propertyName="trimPathStart" + android:valueFrom="0.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_2" /> + </set> +</set> diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_5_path_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_5_path_animation.xml new file mode 100644 index 000000000000..a1cf8df403f6 --- /dev/null +++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_5_path_animation.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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" > + <objectAnimator + android:duration="150" + android:propertyName="trimPathStart" + android:valueFrom="0.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> +</set> diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_6_path_0_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_6_path_0_animation.xml new file mode 100644 index 000000000000..f88c07023dd5 --- /dev/null +++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_6_path_0_animation.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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" > + <objectAnimator + android:duration="250" + android:propertyName="trimPathEnd" + android:valueFrom="0.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0" /> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="133" + android:propertyName="trimPathStart" + android:valueFrom="0.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="216" + android:propertyName="trimPathStart" + android:valueFrom="0.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0" /> + </set> +</set> diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_6_path_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_6_path_animation.xml new file mode 100644 index 000000000000..ada7c10a1073 --- /dev/null +++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_6_path_animation.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="16" + android:propertyName="trimPathStart" + android:valueFrom="0.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="216" + android:propertyName="trimPathStart" + android:valueFrom="0.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + </set> +</set> diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_7_path_0_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_7_path_0_animation.xml new file mode 100644 index 000000000000..e6b12da6e629 --- /dev/null +++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_7_path_0_animation.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="16" + android:propertyName="trimPathEnd" + android:valueFrom="0.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="216" + android:propertyName="trimPathEnd" + android:valueFrom="0.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="133" + android:propertyName="trimPathStart" + android:valueFrom="0.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="266" + android:propertyName="trimPathStart" + android:valueFrom="0.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_2" /> + </set> +</set> diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_7_path_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_7_path_animation.xml new file mode 100644 index 000000000000..8c6e71df1441 --- /dev/null +++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_7_path_animation.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="33" + android:propertyName="trimPathStart" + android:valueFrom="0.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="150" + android:propertyName="trimPathStart" + android:valueFrom="0.0" + android:valueTo="1.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + </set> +</set> diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_white_fingerprint_ridges_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_white_fingerprint_ridges_animation.xml new file mode 100644 index 000000000000..c6a462255844 --- /dev/null +++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_white_fingerprint_ridges_animation.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="100" + android:propertyName="rotation" + android:valueFrom="0.0" + android:valueTo="0.0" + android:valueType="floatType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="566" + android:propertyName="rotation" + android:valueFrom="0.0" + android:valueTo="-305.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_3" /> + <objectAnimator + android:duration="1066" + android:propertyName="rotation" + android:valueFrom="-305.0" + android:valueTo="-305.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0" /> + <objectAnimator + android:duration="800" + android:propertyName="rotation" + android:valueFrom="-305.0" + android:valueTo="-720.0" + android:valueType="floatType" + android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0" /> + </set> +</set> diff --git a/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state.xml b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state.xml new file mode 100644 index 000000000000..cc8aba99116a --- /dev/null +++ b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state.xml @@ -0,0 +1,180 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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 + --> +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:name="lockscreen_fingerprint_error_state" + android:width="32dp" + android:viewportWidth="32" + android:height="32dp" + android:viewportHeight="32" > + <group + android:name="white_fingerprint_ridges" + android:translateX="16.125" + android:translateY="19.75" > + <group + android:name="white_fingerprint_ridges_pivot" + android:translateX="33.2085" + android:translateY="30.91685" > + <group + android:name="ridge_5" > + <path + android:name="ridge_5_path" + android:pathData="M -25.3591003418,-24.4138946533 c -0.569000244141,0.106399536133 -1.12660217285,0.140594482422 -1.45460510254,0.140594482422 c -1.29689025879,0.0 -2.53239440918,-0.343307495117 -3.62019348145,-1.12400817871 c -1.67700195312,-1.20349121094 -2.76950073242,-3.17008972168 -2.76950073242,-5.39189147949" + android:strokeColor="#FFFFFFFF" + android:strokeAlpha="0.5" + android:strokeWidth="1.45" + android:strokeLineCap="round" /> + </group> + <group + android:name="ridge_4" > + <path + android:name="ridge_7_path" + android:pathData="M -36.1409912109,-21.7843475342 c -1.00540161133,-1.19300842285 -1.57499694824,-1.9181060791 -2.36520385742,-3.50170898438 c -0.827560424805,-1.65869140625 -1.31352233887,-3.49159240723 -1.31352233887,-5.48489379883 c 0.0,-3.66279602051 2.96932983398,-6.63220214844 6.63221740723,-6.63220214844 c 3.6628112793,0.0 6.63220214844,2.96940612793 6.63220214844,6.63220214844" + android:strokeColor="#FFFFFFFF" + android:strokeAlpha="0.5" + android:strokeWidth="1.45" + android:strokeLineCap="round" /> + </group> + <group + android:name="ridge_3" > + <path + android:name="ridge_6_path" + android:pathData="M -42.1907958984,-25.6756896973 c -0.758117675781,-2.14370727539 -0.896545410156,-3.86891174316 -0.896545410156,-5.12921142578 c 0.0,-1.46069335938 0.249176025391,-2.84799194336 0.814682006836,-4.09748840332 c 1.56153869629,-3.45030212402 5.03434753418,-5.85076904297 9.0679473877,-5.85076904297 c 5.49430847168,0.0 9.94830322266,4.4539642334 9.94830322266,9.94825744629 c 0.0,1.83151245117 -1.48460388184,3.31610107422 -3.31610107422,3.31610107422 c -1.83149719238,0.0 -3.31610107422,-1.48469543457 -3.31610107422,-3.31610107422 c 0.0,-1.83139038086 -1.48458862305,-3.31610107422 -3.31610107422,-3.31610107422 c -1.83149719238,0.0 -3.31610107422,1.48471069336 -3.31610107422,3.31610107422 c 0.0,2.57020568848 0.989517211914,4.88710021973 2.60510253906,6.5865020752 c 1.22210693359,1.28550720215 2.43139648438,2.09950256348 4.47590637207,2.69030761719" + android:strokeColor="#FFFFFFFF" + android:strokeAlpha="0.5" + android:strokeWidth="1.45" + android:strokeLineCap="round" /> + </group> + <group + android:name="ridge_2" > + <path + android:name="ridge_2_path" + android:pathData="M -44.0646514893,-38.1672973633 c 1.19026184082,-1.77430725098 2.67503356934,-3.24531555176 4.55902099609,-4.27278137207 c 1.88395690918,-1.0274810791 4.04466247559,-1.61137390137 6.34175109863,-1.61137390137 c 2.28761291504,0.0 4.43991088867,0.579071044922 6.31831359863,1.59861755371 c 1.8784942627,1.01954650879 3.36059570312,2.4796295166 4.55279541016,4.24153137207" + android:strokeColor="#FFFFFFFF" + android:strokeAlpha="0.5" + android:strokeWidth="1.45" + android:strokeLineCap="round" /> + </group> + <group + android:name="ridge_1" + android:translateX="-97.5" + android:translateY="-142.5" > + <path + android:name="ridge_1_path" + android:pathData="M 71.7812347412,97.0507202148 c -2.27149963379,-1.31344604492 -4.71360778809,-2.07006835938 -7.56221008301,-2.07006835938 c -2.84869384766,0.0 -5.23320007324,0.779556274414 -7.34411621094,2.07006835938" + android:strokeColor="#FFFFFFFF" + android:strokeAlpha="0.5" + android:strokeWidth="1.45" + android:strokeLineCap="round" /> + </group> + </group> + </group> + <group + android:name="fingerprint_ridges" + android:translateX="16.125" + android:translateY="19.75" > + <group + android:name="fingerprint_ridges_pivot" + android:translateX="33.2085" + android:translateY="30.91685" > + <group + android:name="ridge_6" > + <path + android:name="ridge_5_path_0" + android:pathData="M -25.3591003418,-24.4138946533 c -0.569000244141,0.106399536133 -1.12660217285,0.140594482422 -1.45460510254,0.140594482422 c -1.29689025879,0.0 -2.53239440918,-0.343307495117 -3.62019348145,-1.12400817871 c -1.67700195312,-1.20349121094 -2.76950073242,-3.17008972168 -2.76950073242,-5.39189147949" + android:strokeColor="#FFF2501D" + android:strokeWidth="1.45" + android:strokeLineCap="round" + android:trimPathEnd="0" /> + </group> + <group + android:name="ridge_7" > + <path + android:name="ridge_7_path_0" + android:pathData="M -36.1409912109,-21.7843475342 c -1.00540161133,-1.19300842285 -1.57499694824,-1.9181060791 -2.36520385742,-3.50170898438 c -0.827560424805,-1.65869140625 -1.31352233887,-3.49159240723 -1.31352233887,-5.48489379883 c 0.0,-3.66279602051 2.96932983398,-6.63220214844 6.63221740723,-6.63220214844 c 3.6628112793,0.0 6.63220214844,2.96940612793 6.63220214844,6.63220214844" + android:strokeColor="#FFF2501D" + android:strokeWidth="1.45" + android:strokeLineCap="round" + android:trimPathEnd="0" /> + </group> + <group + android:name="ridge_8" > + <path + android:name="ridge_6_path_0" + android:pathData="M -42.1907958984,-25.6756896973 c -0.758117675781,-2.14370727539 -0.896545410156,-3.86891174316 -0.896545410156,-5.12921142578 c 0.0,-1.46069335938 0.249176025391,-2.84799194336 0.814682006836,-4.09748840332 c 1.56153869629,-3.45030212402 5.03434753418,-5.85076904297 9.0679473877,-5.85076904297 c 5.49430847168,0.0 9.94830322266,4.4539642334 9.94830322266,9.94825744629 c 0.0,1.83151245117 -1.48460388184,3.31610107422 -3.31610107422,3.31610107422 c -1.83149719238,0.0 -3.31610107422,-1.48469543457 -3.31610107422,-3.31610107422 c 0.0,-1.83139038086 -1.48458862305,-3.31610107422 -3.31610107422,-3.31610107422 c -1.83149719238,0.0 -3.31610107422,1.48471069336 -3.31610107422,3.31610107422 c 0.0,2.57020568848 0.989517211914,4.88710021973 2.60510253906,6.5865020752 c 1.22210693359,1.28550720215 2.43139648438,2.09950256348 4.47590637207,2.69030761719" + android:strokeColor="#FFF2501D" + android:strokeWidth="1.45" + android:strokeLineCap="round" + android:trimPathEnd="0" /> + </group> + <group + android:name="ridge_9" > + <path + android:name="ridge_2_path_0" + android:pathData="M -44.0646514893,-38.1672973633 c 1.19026184082,-1.77430725098 2.67503356934,-3.24531555176 4.55902099609,-4.27278137207 c 1.88395690918,-1.0274810791 4.04466247559,-1.61137390137 6.34175109863,-1.61137390137 c 2.28761291504,0.0 4.43991088867,0.579071044922 6.31831359863,1.59861755371 c 1.8784942627,1.01954650879 3.36059570312,2.4796295166 4.55279541016,4.24153137207" + android:strokeColor="#FFF2501D" + android:strokeWidth="1.45" + android:strokeLineCap="round" + android:trimPathStart="1" /> + </group> + <group + android:name="ridge_10" + android:translateX="-97.5" + android:translateY="-142.5" > + <path + android:name="ridge_1_path_0" + android:pathData="M 71.7812347412,97.0507202148 c -2.27149963379,-1.31344604492 -4.71360778809,-2.07006835938 -7.56221008301,-2.07006835938 c -2.84869384766,0.0 -5.23320007324,0.779556274414 -7.34411621094,2.07006835938" + android:strokeColor="#FFF2501D" + android:strokeWidth="1.45" + android:strokeLineCap="round" + android:trimPathEnd="0" /> + </group> + </group> + </group> + <group + android:name="exclamation" + android:translateX="16" + android:translateY="16" > + <group + android:name="group_2" + android:scaleX="0" + android:scaleY="0" + android:rotation="184" > + <path + android:name="path_2_merged" + android:pathData="M 1.35900878906,6.76104736328 c 0.0,0.0 -2.69998168945,0.0 -2.69998168945,0.0 c 0.0,0.0 0.0,-2.69995117188 0.0,-2.69995117188 c 0.0,0.0 2.69998168945,0.0 2.69998168945,0.0 c 0.0,0.0 0.0,2.69995117188 0.0,2.69995117188 Z M 1.35363769531,1.36633300781 c 0.0,0.0 -2.69998168945,0.0 -2.69998168945,0.0 c 0.0,0.0 0.0,-8.09997558594 0.0,-8.09997558594 c 0.0,0.0 2.69998168945,0.0 2.69998168945,0.0 c 0.0,0.0 0.0,8.09997558594 0.0,8.09997558594 Z" + android:fillColor="#FFF2501D" /> + </group> + </group> + <group + android:name="circle_outline" + android:translateX="16" + android:translateY="16" > + <group + android:name="group_1" + android:scaleX="1.12734" + android:scaleY="1.12734" + android:rotation="285" > + <path + android:name="path_3" + android:pathData="M 0.0101470947266,10.8087768555 c -5.96701049805,0.0 -10.8000183105,-4.8330078125 -10.8000183105,-10.8000488281 c 0.0,-5.96691894531 4.8330078125,-10.7999267578 10.8000183105,-10.7999267578 c 5.96697998047,0.0 10.799987793,4.8330078125 10.799987793,10.7999267578 c 0.0,5.96704101562 -4.8330078125,10.8000488281 -10.799987793,10.8000488281 Z" + android:strokeColor="#FFF2501D" + android:strokeWidth="2" + android:trimPathStart="1" /> + </group> + </group> +</vector> diff --git a/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_animation.xml b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_animation.xml new file mode 100644 index 000000000000..8cc8ac2172a2 --- /dev/null +++ b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_animation.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/lockscreen_fingerprint_error_state" > + <target + android:name="white_fingerprint_ridges" + android:animation="@anim/lockscreen_fingerprint_error_state_white_fingerprint_ridges_animation" /> + <target + android:name="ridge_5_path" + android:animation="@anim/lockscreen_fingerprint_error_state_ridge_5_path_animation" /> + <target + android:name="ridge_7_path" + android:animation="@anim/lockscreen_fingerprint_error_state_ridge_7_path_animation" /> + <target + android:name="ridge_6_path" + android:animation="@anim/lockscreen_fingerprint_error_state_ridge_6_path_animation" /> + <target + android:name="ridge_2_path" + android:animation="@anim/lockscreen_fingerprint_error_state_ridge_2_path_animation" /> + <target + android:name="ridge_1_path" + android:animation="@anim/lockscreen_fingerprint_error_state_ridge_1_path_animation" /> + <target + android:name="fingerprint_ridges" + android:animation="@anim/lockscreen_fingerprint_error_state_fingerprint_ridges_animation" /> + <target + android:name="ridge_5_path_0" + android:animation="@anim/lockscreen_fingerprint_error_state_ridge_5_path_0_animation" /> + <target + android:name="ridge_7_path_0" + android:animation="@anim/lockscreen_fingerprint_error_state_ridge_7_path_0_animation" /> + <target + android:name="ridge_6_path_0" + android:animation="@anim/lockscreen_fingerprint_error_state_ridge_6_path_0_animation" /> + <target + android:name="ridge_2_path_0" + android:animation="@anim/lockscreen_fingerprint_error_state_ridge_2_path_0_animation" /> + <target + android:name="ridge_1_path_0" + android:animation="@anim/lockscreen_fingerprint_error_state_ridge_1_path_0_animation" /> + <target + android:name="group_2" + android:animation="@anim/lockscreen_fingerprint_error_state_group_2_animation" /> + <target + android:name="group_1" + android:animation="@anim/lockscreen_fingerprint_error_state_group_1_animation" /> + <target + android:name="path_3" + android:animation="@anim/lockscreen_fingerprint_error_state_path_3_animation" /> +</animated-vector> diff --git a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0.xml new file mode 100644 index 000000000000..39c5211fe4f0 --- /dev/null +++ b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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 + --> +<pathInterpolator + xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0.0,0.0 c 0.16666666667,0.0 0.83333333333,1.0 1.0,1.0" /> diff --git a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_1.xml b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_1.xml new file mode 100644 index 000000000000..d3ae9d74ec06 --- /dev/null +++ b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_1.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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 + --> +<pathInterpolator + xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0.0,0.0 c 0.0,0.0 0.6,1.0 1.0,1.0" /> diff --git a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_2.xml b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_2.xml new file mode 100644 index 000000000000..e10db01ac697 --- /dev/null +++ b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_2.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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 + --> +<pathInterpolator + xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0.0,0.0 c 0.8,0.0 0.5,1.0 1.0,1.0" /> diff --git a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_3.xml b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_3.xml new file mode 100644 index 000000000000..736eac68f9ca --- /dev/null +++ b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_3.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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 + --> +<pathInterpolator + xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0.0,0.0 c 0.4,0.0 0.6,1.0 1.0,1.0" /> diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml index fca82318aea4..105746476b2a 100644 --- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml +++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml @@ -61,7 +61,7 @@ android:scaleType="center" android:contentDescription="@string/accessibility_phone_button" /> - <com.android.systemui.statusbar.KeyguardAffordanceView + <com.android.systemui.statusbar.phone.LockIcon android:id="@+id/lock_icon" android:layout_width="@dimen/keyguard_affordance_width" android:layout_height="@dimen/keyguard_affordance_height" diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml index 2eb99ba67066..ddff0f031fb6 100644 --- a/packages/SystemUI/res/layout/qs_detail.xml +++ b/packages/SystemUI/res/layout/qs_detail.xml @@ -18,7 +18,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/qs_detail_background" - android:paddingBottom="16dp" + android:paddingBottom="8dp" android:orientation="vertical"> <FrameLayout @@ -30,7 +30,7 @@ <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingEnd="16dp" + android:paddingEnd="8dp" android:gravity="end"> <TextView diff --git a/packages/SystemUI/res/layout/segmented_button.xml b/packages/SystemUI/res/layout/segmented_button.xml index ead735fae26e..b7a79329c623 100644 --- a/packages/SystemUI/res/layout/segmented_button.xml +++ b/packages/SystemUI/res/layout/segmented_button.xml @@ -19,10 +19,10 @@ android:layout_height="wrap_content" android:layout_marginStart="@dimen/segmented_button_spacing" android:layout_weight="1" - android:paddingStart="8dp" - android:gravity="start|center_vertical" + android:gravity="center" android:maxLines="2" + android:lineSpacingMultiplier="1.05026" android:textColor="@color/segmented_button_text_selector" android:background="@drawable/btn_borderless_rect" - android:textAppearance="@style/TextAppearance.Volume.ZenSwitchSummary" - android:minHeight="48dp" /> + android:textAppearance="@style/TextAppearance.QS.SegmentedButton" + android:minHeight="64dp" /> diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml index c86e9dc71265..0ed1e2ac4cdb 100644 --- a/packages/SystemUI/res/layout/volume_dialog.xml +++ b/packages/SystemUI/res/layout/volume_dialog.xml @@ -21,40 +21,31 @@ android:layout_marginBottom="4dp" android:layout_marginLeft="@dimen/notification_side_padding" android:layout_marginRight="@dimen/notification_side_padding" - android:layout_marginTop="4dp" android:background="@drawable/volume_dialog_background" android:translationZ="4dp" > <com.android.keyguard.AlphaOptimizedImageButton android:id="@+id/volume_expand_button" style="@style/VolumeButtons" - android:layout_alignParentLeft="true" android:layout_width="@dimen/volume_button_size" android:layout_height="@dimen/volume_button_size" + android:layout_alignParentLeft="true" android:clickable="true" android:soundEffectsEnabled="false" - android:src="@drawable/ic_volume_collapse_animation" /> + android:src="@drawable/ic_volume_collapse_animation" + tools:ignore="RtlHardcoded" /> <LinearLayout android:id="@+id/volume_dialog_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" - android:paddingBottom="4dp" - android:paddingTop="6dp" > + android:paddingBottom="8dp" + android:paddingTop="8dp" > <!-- volume rows added and removed here! :-) --> - <FrameLayout - android:id="@+id/volume_footer" - android:layout_width="match_parent" - android:layout_height="wrap_content" - tools:ignore="UselessParent" > - - <include layout="@layout/volume_text_footer" /> - - <include layout="@layout/volume_zen_footer" /> - </FrameLayout> + <include layout="@layout/volume_zen_footer" /> </LinearLayout> </RelativeLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml index b51aa962c485..53ae61bca438 100644 --- a/packages/SystemUI/res/layout/volume_dialog_row.xml +++ b/packages/SystemUI/res/layout/volume_dialog_row.xml @@ -16,16 +16,15 @@ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingStart="4dp" - android:paddingEnd="4dp" - android:clipChildren="false" > + android:clipChildren="false" + android:paddingEnd="8dp" + android:paddingStart="8dp" > <TextView android:id="@+id/volume_row_header" style="?android:attr/textAppearanceButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:alpha="@dimen/volume_secondary_alpha" android:ellipsize="end" android:maxLines="1" android:paddingBottom="0dp" @@ -50,8 +49,8 @@ android:layout_below="@id/volume_row_header" android:layout_toEndOf="@id/volume_row_icon" android:layout_toStartOf="@+id/volume_settings_button" - android:paddingEnd="4dp" - android:paddingStart="4dp" + android:paddingEnd="8dp" + android:paddingStart="8dp" android:progressTint="@android:color/white" android:thumbTint="@android:color/white" /> diff --git a/packages/SystemUI/res/layout/volume_text_footer.xml b/packages/SystemUI/res/layout/volume_text_footer.xml deleted file mode 100644 index 7436488da680..000000000000 --- a/packages/SystemUI/res/layout/volume_text_footer.xml +++ /dev/null @@ -1,54 +0,0 @@ -<!-- - Copyright (C) 2015 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" - xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/volume_text_footer" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:visibility="gone" - tools:ignore="UselessParent" > - - <TextView - android:id="@+id/volume_footline_text" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignBaseline="@+id/volume_footline_action_button" - android:alpha="@dimen/volume_secondary_alpha" - android:fontFamily="sans-serif" - android:paddingEnd="8dp" - android:paddingStart="13dp" - android:textColor="?android:attr/textColorPrimary" /> - - <Button - android:id="@+id/volume_footline_action_button" - style="@android:style/Widget.Material.Button.Borderless" - android:layout_width="wrap_content" - android:layout_height="@dimen/volume_button_size" - android:layout_toEndOf="@id/volume_footline_text" - android:layout_toStartOf="@+id/volume_settings_button" - android:alpha="@dimen/volume_secondary_alpha" - android:paddingEnd="0dp" - android:paddingStart="0dp" /> - - <com.android.keyguard.AlphaOptimizedImageButton - android:id="@+id/volume_settings_button" - style="@style/VolumeButtons" - android:layout_width="@dimen/volume_button_size" - android:layout_height="@dimen/volume_button_size" - android:layout_alignParentEnd="true" - android:src="@drawable/ic_volume_settings" /> - -</RelativeLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/volume_zen_footer.xml b/packages/SystemUI/res/layout/volume_zen_footer.xml index dcdc859be496..9e761e2142a5 100644 --- a/packages/SystemUI/res/layout/volume_zen_footer.xml +++ b/packages/SystemUI/res/layout/volume_zen_footer.xml @@ -20,93 +20,58 @@ android:layout_height="wrap_content" android:orientation="vertical" > <!-- extends LinearLayout --> + <View + android:id="@+id/zen_embedded_divider" + android:layout_width="match_parent" + android:layout_height="1dp" + android:layout_marginBottom="8dp" + android:layout_marginTop="8dp" + android:background="#4dffffff" /> + <LinearLayout - android:id="@+id/volume_zen_switch_bar" android:layout_width="match_parent" - android:layout_height="@dimen/volume_button_size" - android:layout_marginStart="4dp" - android:layout_marginEnd="4dp" - android:clickable="true" - android:orientation="horizontal" > + android:layout_height="wrap_content" + android:gravity="center_vertical" + android:orientation="horizontal" + android:paddingEnd="8dp" + android:paddingStart="8dp" > <ImageView - android:id="@+id/volume_zen_switch_bar_icon" + android:id="@+id/volume_zen_icon" android:layout_width="@dimen/volume_button_size" android:layout_height="@dimen/volume_button_size" + android:layout_marginEnd="7dp" android:scaleType="center" android:src="@drawable/ic_dnd" /> - <TextView + <LinearLayout android:layout_width="0dp" - android:layout_height="fill_parent" - android:layout_weight="1" - android:gravity="center_vertical" - android:textDirection="locale" - android:padding="3dp" - android:text="@string/volume_zen_switch_text" - android:textAppearance="@style/TextAppearance.Volume.ZenSwitch" /> - - <Switch - android:id="@+id/volume_zen_switch" - android:layout_width="wrap_content" - android:layout_height="fill_parent" - android:layout_marginEnd="11dp" /> - - </LinearLayout> - - <RelativeLayout - android:id="@+id/volume_zen_panel_summary" - android:layout_width="match_parent" - android:layout_height="@dimen/volume_button_size" - android:layout_marginStart="@dimen/volume_button_size" - android:paddingEnd="7dp" - android:paddingStart="7dp" > - - <TextView - android:id="@+id/volume_zen_panel_summary_line_1" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:textAppearance="@style/TextAppearance.Volume.ZenSwitchSummary" /> - - <TextView - android:id="@+id/volume_zen_panel_summary_line_2" - android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_below="@id/volume_zen_panel_summary_line_1" - android:textAppearance="@style/TextAppearance.Volume.ZenSwitchDetail" /> - </RelativeLayout> - - <include layout="@layout/zen_mode_panel" /> + android:layout_weight="1" + android:orientation="vertical" > - <LinearLayout - android:id="@+id/volume_zen_mode_panel_buttons" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="4dp" - android:layout_marginEnd="4dp" - android:gravity="end" > + <TextView + android:id="@+id/volume_zen_summary_line_1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textAppearance="@style/TextAppearance.Volume.ZenSummary" /> - <TextView - android:id="@+id/volume_zen_mode_panel_more" - style="@style/QSBorderlessButton" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="8dp" - android:clickable="true" - android:focusable="true" - android:minWidth="132dp" - android:text="@string/quick_settings_more_settings" - android:textAppearance="@style/TextAppearance.QS.DetailButton" /> + <TextView + android:id="@+id/volume_zen_summary_line_2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textAppearance="@style/TextAppearance.Volume.ZenDetail" /> + </LinearLayout> <TextView - android:id="@+id/volume_zen_mode_panel_done" + android:id="@+id/volume_zen_end_now" style="@style/QSBorderlessButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="true" android:focusable="true" - android:minWidth="66dp" - android:text="@string/quick_settings_done" + android:minWidth="91dp" + android:text="@string/volume_zen_end_now" android:textAppearance="@style/TextAppearance.QS.DetailButton" /> </LinearLayout> diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml index b676bce94de9..595c9ede07a7 100644 --- a/packages/SystemUI/res/layout/zen_mode_panel.xml +++ b/packages/SystemUI/res/layout/zen_mode_panel.xml @@ -22,81 +22,21 @@ android:clipChildren="false" android:orientation="vertical" > - <FrameLayout - android:id="@+id/zen_buttons_container" + <com.android.systemui.volume.SegmentedButtons + android:id="@+id/zen_buttons" android:layout_width="match_parent" android:layout_height="wrap_content" - android:minHeight="8dp" - android:layout_marginStart="39dp" - android:elevation="4dp" - android:background="@drawable/qs_background_secondary" > - - <com.android.systemui.volume.SegmentedButtons - android:id="@+id/zen_buttons" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginLeft="8dp" - android:layout_marginRight="8dp" - android:layout_marginBottom="8dp" - android:clipChildren="false" /> - </FrameLayout> + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" /> <View android:id="@+id/zen_embedded_divider" android:layout_width="match_parent" + android:layout_marginTop="8dp" android:layout_height="1dp" - android:visibility="gone" android:background="#4dffffff" /> <RelativeLayout - android:id="@+id/zen_subhead" - android:layout_width="match_parent" - android:layout_height="62dp" - android:layout_marginStart="39dp" - android:gravity="center_vertical" - android:paddingLeft="8dp" - android:paddingRight="8dp" > - - <TextView - android:id="@+id/zen_subhead_collapsed" - android:layout_width="wrap_content" - android:layout_height="48dp" - android:layout_gravity="center_vertical" - android:gravity="center_vertical" - android:paddingLeft="8dp" - android:paddingRight="4dp" - android:background="@drawable/btn_borderless_rect" - android:clickable="true" - android:drawableEnd="@drawable/qs_subhead_caret" - android:maxLines="2" - android:ellipsize="end" - android:textAppearance="@style/TextAppearance.QS.Subhead" /> - - <TextView - android:id="@+id/zen_subhead_expanded" - android:layout_width="wrap_content" - android:layout_height="48dp" - android:layout_gravity="center_vertical" - android:gravity="center_vertical" - android:paddingLeft="8dp" - android:maxLines="2" - android:ellipsize="end" - android:textAppearance="@style/TextAppearance.QS.Subhead" /> - - <ImageView - android:id="@+id/zen_more_settings" - android:layout_width="48dp" - android:layout_height="48dp" - android:layout_alignParentEnd="true" - android:background="@drawable/btn_borderless_rect" - android:clickable="true" - android:contentDescription="@string/accessibility_desc_settings" - android:scaleType="center" - android:src="@drawable/ic_settings" /> - - </RelativeLayout> - - <RelativeLayout android:id="@+id/zen_introduction" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -122,10 +62,9 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" - android:layout_marginStart="55dp" + android:layout_marginStart="24dp" android:lineSpacingMultiplier="1.20029" android:layout_toStartOf="@id/zen_introduction_confirm" - android:text="@string/zen_priority_introduction" android:textAppearance="@style/TextAppearance.QS.Introduction" /> <TextView @@ -141,6 +80,12 @@ android:text="@string/zen_priority_customize_button" android:textAppearance="@style/TextAppearance.QS.DetailButton.White" /> + <View + android:layout_width="0dp" + android:layout_height="16dp" + android:layout_below="@id/zen_introduction_message" + android:layout_alignParentEnd="true" /> + </RelativeLayout> <LinearLayout @@ -149,7 +94,7 @@ android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginEnd="4dp" - android:layout_marginStart="39dp" + android:layout_marginStart="4dp" android:orientation="vertical" android:paddingBottom="@dimen/zen_mode_condition_detail_bottom_padding" /> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 2822445f7094..70890b30961f 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -230,7 +230,7 @@ <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"Ruutu on nyt lukittu vaakasuuntaan."</string> <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"Ruutu on nyt lukittu pystysuuntaan."</string> <string name="dessert_case" msgid="1295161776223959221">"Jälkiruokavitriini"</string> - <string name="start_dreams" msgid="7219575858348719790">"Unelmat"</string> + <string name="start_dreams" msgid="7219575858348719790">"Lepotila"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Älä häiritse"</string> <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Vain tärkeät"</string> diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml index b0cc00a19953..97d6ba2983e7 100644 --- a/packages/SystemUI/res/values-ne-rNP/strings.xml +++ b/packages/SystemUI/res/values-ne-rNP/strings.xml @@ -168,7 +168,7 @@ <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"स्क्रीन बन्द गर्नुहोस्।"</string> <string name="accessibility_desc_settings" msgid="3417884241751434521">"सेटिङहरू"</string> <string name="accessibility_desc_recent_apps" msgid="4876900986661819788">"सारांश।"</string> - <string name="accessibility_desc_confirm" msgid="3446792278337969766">"निश्चित गर्नुहोस्"</string> + <string name="accessibility_desc_confirm" msgid="3446792278337969766">"पुष्टि गर्नुहोस्"</string> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"प्रयोगकर्ता <xliff:g id="USER">%s</xliff:g>।"</string> <string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>।"</string> <string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"वाइफाइ बन्द गरियो।"</string> @@ -303,7 +303,7 @@ <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>को लागि माथि धिसार्नुहोस्"</string> <string name="description_direction_left" msgid="7207478719805562165">"स्लाइड <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>को लागि बायाँ।"</string> <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"कुनै रुकावट छैन। चेतावनी समेत छैन।"</string> - <string name="zen_priority_introduction" msgid="7253045784560169993">"अलार्म, अनुस्मारक, घटनाहरु, र तपाईँले निर्दिष्ट कल देखि बाहेक, आवाज र कंपनले तपाईँ व्याकुल हुनुहुने छैन।"</string> + <string name="zen_priority_introduction" msgid="7253045784560169993">"अलार्म, रिमाइन्डर, घटना, र तपाईँले निर्दिष्ट गर्नुहुने कलरहरू बाहेक, आवाज र कंपनले तपाईँ वाधा गर्ने छैन।"</string> <string name="zen_priority_customize_button" msgid="7948043278226955063">"अनुकूलन गर्नुहोस्"</string> <string name="zen_no_interruptions" msgid="7970973750143632592">"कुनै रुकावटहरू छैन"</string> <string name="zen_important_interruptions" msgid="3477041776609757628">"प्राथमिकता रुकावटहरूमा मात्र"</string> @@ -341,8 +341,8 @@ <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"सुरु गर्नुहोस्"</string> <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"हो, जारी राख्नुहोस्"</string> <string name="guest_notification_title" msgid="1585278533840603063">"अतिथि प्रयोगकर्ता"</string> - <string name="guest_notification_text" msgid="7513706222848825467">"अनुप्रयोगहरू र डेटा मेटाउन अतिथिलाई निकाल्नु"</string> - <string name="guest_notification_remove_action" msgid="8820670703892101990">"REMOVE GUEST"</string> + <string name="guest_notification_text" msgid="7513706222848825467">"अनुप्रयोगहरू र डेटा मेटाउन अतिथिलाई निकाल्नुहोस्"</string> + <string name="guest_notification_remove_action" msgid="8820670703892101990">"अतिथिलाई हटाउनुहोस्"</string> <string name="user_add_user_title" msgid="4553596395824132638">"नयाँ प्रयोगकर्ता थप्नुहुन्छ?"</string> <string name="user_add_user_message_short" msgid="2161624834066214559">"जब तपाईँले नयाँ प्रयोगकर्ता थप्नुहुन्छ, त्यस प्रयोगकर्ताले आफ्नो स्थान स्थापना गर्न पर्ने छ।\n\nकुनै पनि प्रयोगकर्ताले सबै अन्य प्रयोगकर्ताहरूका लागि अनुप्रयोगहरू अद्यावधिक गर्न सक्छन्।"</string> <string name="battery_saver_notification_title" msgid="237918726750955859">"ब्याट्रि सेभर चालु छ"</string> @@ -362,13 +362,13 @@ <string name="monitoring_title" msgid="169206259253048106">"सञ्जाल अनुगमन"</string> <string name="disable_vpn" msgid="4435534311510272506">"VPN असक्षम गर्नुहोस्"</string> <string name="disconnect_vpn" msgid="1324915059568548655">"विच्छेद VPN"</string> - <string name="monitoring_description_device_owned" msgid="5780988291898461883">"तपाईँको उपकरण <xliff:g id="ORGANIZATION">%1$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\n\n तपाईँको प्रशासकले सेटिङहरू, कर्पोरेट पहुँच, अनुप्रयोगहरू, आफ्नो उपकरण सम्बन्धित डेटा, र उपकरणको स्थानीय जानकारीको अनुगमन तथा व्यवस्थापन गर्न सक्छ। थप जानकारीको लागि, आफ्नो प्रशासक संग सम्पर्क राख्नुहोस्।"</string> - <string name="monitoring_description_profile_owned" msgid="8110044290898637925">"तपाईँको कार्य प्रोफाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\n\n तपाईँको प्रशासक इमेल, अनुप्रयोगहरू, र सुरक्षित वेबसाइटहरू सहित आफ्नो सञ्जाल गतिविधि अनुगमन गर्न सक्षम छ।\n\n थप जानकारीको लागि, आफ्नो प्रशासक संग सम्पर्क राख्नुहोस्।"</string> - <string name="monitoring_description_device_and_profile_owned" msgid="1664428184778531249">"तपाईँको उपकरण \n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\n तपाईँको कार्य प्रोफाइल \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\n\n तपाईँको प्रशासकले इमेल, अनुप्रयोगहरू, र सुरक्षित वेबसाइटहरू सहित आफ्नो उपकरण र सञ्जाल गतिविधि अनुगमन गर्न सक्छ।\n\n थप जानकारीको लागि, आफ्नो प्रशासक संग सम्पर्क राख्नुहोस्।"</string> - <string name="monitoring_description_vpn" msgid="912328761766161919">"तपाईँले VPN जडान गर्न अनुप्रयोगलाई अनुमति दिनुभयो।\n\nयो अनुप्रयोगले तपाईको यन्त्र र नेटवर्क गतिविधि, इमेलहरु सम्मिलित, अनुप्रयोगहरू र सुरक्षित वेबसाइटहरू।"</string> - <string name="monitoring_description_vpn_device_owned" msgid="3090670777499161246">"तपाईँको उपकरण <xliff:g id="ORGANIZATION">%1$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\n\n तपाईँको प्रशासकले सेटिङ्हरू, कर्पोरेट पहुँच, अनुप्रयोगहरू, आफ्नो उपकरण सम्बन्धित डेटा, र उपकरणको स्थानीय जानकारीको अनुगमन तथा व्यवस्थापन गर्न सक्छ।\n\nतपाईँ VPN संग जडित हुनुहुन्छ, जसले तपाईँको इमेल, अनुप्रयोगहरू, र वेबसाइटहरू सहित आफ्नो सञ्जाल गतिविधि अनुगमन गर्न सक्छ। \n\nथप जानकारीको लागि, आफ्नो प्रशासक संग सम्पर्क राख्नुहोस्।"</string> - <string name="monitoring_description_vpn_profile_owned" msgid="2224494839524715272">"तपाईँको कार्य प्रोफाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\n\n तपाईँको प्रशासकले इमेल, अनुप्रयोगहरू, र सुरक्षित वेबसाइटहरू सहित आफ्नो सञ्जाल गतिविधि अनुगमन गर्न सक्षम छ।\n\n थप जानकारीको लागि, आफ्नो प्रशासक संग सम्पर्क राख्नुहोस्।\n\n तपाईँ VPN संग पनि जडित हुनुहुन्छ, जसले आफ्नो सञ्जाल गतिविधि अनुगमन गर्न सक्छ।"</string> - <string name="monitoring_description_vpn_device_and_profile_owned" msgid="2198546817407897093">"तपाईँको उपकरण <xliff:g id="ORGANIZATION_0">%1$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\nतपाईँको कार्य प्रोफाइल \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\n\n तपाईँको प्रशासक इमेल, अनुप्रयोगहरू, र सुरक्षित वेबसाइटहरू सहित आफ्नो सञ्जाल गतिविधि अनुगमन गर्न सक्षम छ।\n\n थप जानकारीको लागि, आफ्नो प्रशासक संग सम्पर्क राख्नुहोस्।\n\n तपाईँ VPN संग पनि जडित हुनुहुन्छ, जसले आफ्नो व्यक्तिगत सञ्जाल गतिविधि अनुगमन गर्न सक्छ।"</string> + <string name="monitoring_description_device_owned" msgid="5780988291898461883">"तपाईँको यन्त्र <xliff:g id="ORGANIZATION">%1$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\n\n तपाईँको प्रशासकले सेटिङहरू, कर्पोरेट पहुँच, अनुप्रयोगहरू, आफ्नो उपकरण सम्बन्धित डेटा, र उपकरणको स्थानीय जानकारीको अनुगमन तथा व्यवस्थापन गर्न सक्छ। थप जानकारीको लागि, आफ्नो प्रशासकसँग सम्पर्क राख्नुहोस्।"</string> + <string name="monitoring_description_profile_owned" msgid="8110044290898637925">"तपाईँको कार्य प्रोफाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\n\n तपाईँको प्रशासक इमेल, अनुप्रयोगहरू, र सुरक्षित वेबसाइटहरू सहित आफ्नो सञ्जाल गतिविधि अनुगमन गर्न सक्षम छ।\n\n थप जानकारीको लागि, आफ्नो प्रशासकससँग सम्पर्क राख्नुहोस्।"</string> + <string name="monitoring_description_device_and_profile_owned" msgid="1664428184778531249">"तपाईँको यन्त्र \n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\n तपाईँको कार्य प्रोफाइल \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\n\n तपाईँको प्रशासकले इमेल, अनुप्रयोगहरू, र सुरक्षित वेबसाइटहरू सहित आफ्नो उपकरण र सञ्जाल गतिविधि अनुगमन गर्न सक्छ।\n\n थप जानकारीको लागि, आफ्नो प्रशासकसँग सम्पर्क राख्नुहोस्।"</string> + <string name="monitoring_description_vpn" msgid="912328761766161919">"तपाईँले VPN जडान गर्न अनुप्रयोगलाई अनुमति दिनुभयो।\n\nयो अनुप्रयोगले तपाईको यन्त्र र नेटवर्क गतिविधि, इमेलहरु सम्मिलित, अनुप्रयोगहरू र सुरक्षित वेबसाइटहरूका अनुगमन गर्नसक्छ।"</string> + <string name="monitoring_description_vpn_device_owned" msgid="3090670777499161246">"तपाईँको यन्त्र <xliff:g id="ORGANIZATION">%1$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\n\n तपाईँको प्रशासकले सेटिङ्हरू, कर्पोरेट पहुँच, अनुप्रयोगहरू, आफ्नो उपकरण सम्बन्धित डेटा, र उपकरणको स्थानीय जानकारीको अनुगमन तथा व्यवस्थापन गर्न सक्छ।\n\nतपाईँ VPN सँग जडित हुनुहुन्छ, जसले तपाईँको इमेल, अनुप्रयोगहरू, र वेबसाइटहरू सहित आफ्नो सञ्जाल गतिविधि अनुगमन गर्न सक्छ। \n\nथप जानकारीको लागि, आफ्नो प्रशासकसँग सम्पर्क राख्नुहोस्।"</string> + <string name="monitoring_description_vpn_profile_owned" msgid="2224494839524715272">"तपाईँको कार्य प्रोफाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\n\n तपाईँको प्रशासकले इमेल, अनुप्रयोगहरू, र सुरक्षित वेबसाइटहरू सहित आफ्नो सञ्जाल गतिविधि अनुगमन गर्न सक्षम छ।\n\n थप जानकारीको लागि, आफ्नो प्रशासकसँग सम्पर्क राख्नुहोस्।\n\n तपाईँ VPN सँग पनि जडित हुनुहुन्छ, जसले आफ्नो सञ्जाल गतिविधि अनुगमन गर्न सक्छ।"</string> + <string name="monitoring_description_vpn_device_and_profile_owned" msgid="2198546817407897093">"तपाईँको यन्त्र <xliff:g id="ORGANIZATION_0">%1$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\nतपाईँको कार्य प्रोफाइल \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g> द्वारा व्यवस्थापन गरिन्छ।\n\n तपाईँको प्रशासक इमेल, अनुप्रयोगहरू, र सुरक्षित वेबसाइटहरू सहित आफ्नो सञ्जाल गतिविधि अनुगमन गर्न सक्षम छ।\n\n थप जानकारीको लागि, आफ्नो प्रशासकसँग सम्पर्क राख्नुहोस्।\n\n तपाईँ VPN सँग पनि जडित हुनुहुन्छ, जसले आफ्नो व्यक्तिगत सञ्जाल गतिविधि अनुगमन गर्न सक्छ।"</string> <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"तपाईँले नखोले सम्म उपकरण बन्द रहनेछ"</string> <string name="hidden_notifications_title" msgid="7139628534207443290">"छिटो सूचनाहरू प्राप्त गर्नुहोस्"</string> <string name="hidden_notifications_text" msgid="2326409389088668981">"तपाईँले अनलक गर्नअघि तिनीहरूलाई हेर्नुहोस्"</string> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 1f1455afd373..7a108ed8883c 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -128,7 +128,7 @@ <color name="screen_pinning_request_window_bg">#80000000</color> <color name="segmented_button_selected">#FFFFFFFF</color> - <color name="segmented_button_unselected">#B3B0BEC5</color><!-- 70% blue grey 200 --> + <color name="segmented_button_unselected">#FFB0BEC5</color><!-- blue grey 200 --> <color name="dark_mode_icon_color_single_tone">#99000000</color> <color name="dark_mode_icon_color_dual_tone_background">#3d000000</color> @@ -139,4 +139,6 @@ <color name="light_mode_icon_color_dual_tone_fill">#ffffff</color> <color name="zen_introduction_message_background">#ff009688</color><!-- deep teal 500 --> + <color name="volume_icon_color">#ffffffff</color> + <color name="volume_settings_icon_color">#7fffffff</color> </resources> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 2e44547d03d2..6e7942345c6a 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -150,7 +150,7 @@ <integer name="heads_up_notification_minimum_time">2000</integer> <!-- milliseconds before the heads up notification accepts touches. --> - <integer name="heads_up_sensitivity_delay">700</integer> + <integer name="touch_acceptance_delay">700</integer> <!-- The duration in seconds to wait before the dismiss buttons are shown. --> <integer name="recents_task_bar_dismiss_delay_seconds">1</integer> @@ -293,5 +293,9 @@ <!-- Duration of the full carrier network change icon animation. --> <integer name="carrier_network_change_anim_time">3000</integer> + + <!-- Duration of the expansion animation in the volume dialog --> + <item name="volume_expand_animation_duration" type="integer">300</item> + </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 6e59029f08bb..a0ef5e2b6b9f 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -573,4 +573,13 @@ <!-- Minimum margin of the notification panel on the side, when being positioned dynamically --> <dimen name="notification_panel_min_side_margin">48dp</dimen> + + <!-- Vertical spacing between multiple volume slider rows --> + <dimen name="volume_slider_interspacing">8dp</dimen> + + <!-- Volume dialog vertical offset from the top of the screen --> + <dimen name="volume_offset_top">0dp</dimen> + + <!-- Standard image button size for volume dialog buttons --> + <dimen name="volume_button_size">48dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index f12fd0c8406a..8b50774b46b8 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -439,7 +439,7 @@ <!-- Content description of the do not disturb tile in quick settings when on in priority (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_quick_settings_dnd_priority_on">Do not disturb on, priority only.</string> <!-- Content description of the do not disturb tile in quick settings when on in none (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_quick_settings_dnd_none_on">Do not disturb on, no interruptions.</string> + <string name="accessibility_quick_settings_dnd_none_on">Do not disturb on, total silence.</string> <!-- Content description of the do not disturb tile in quick settings when on in alarms only (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_quick_settings_dnd_alarms_on">Do not disturb on, alarms only.</string> <!-- Content description of the do not disturb tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] --> @@ -576,8 +576,8 @@ <string name="quick_settings_dnd_priority_label">Priority only</string> <!-- QuickSettings: Do not disturb - Alarms only [CHAR LIMIT=NONE] --> <string name="quick_settings_dnd_alarms_label">Alarms only</string> - <!-- QuickSettings: Do not disturb - No interruptions [CHAR LIMIT=NONE] --> - <string name="quick_settings_dnd_none_label">No interruptions</string> + <!-- QuickSettings: Do not disturb - Total silence [CHAR LIMIT=NONE] --> + <string name="quick_settings_dnd_none_label">Total silence</string> <!-- QuickSettings: Bluetooth [CHAR LIMIT=NONE] --> <string name="quick_settings_bluetooth_label">Bluetooth</string> <!-- QuickSettings: Bluetooth (Multiple) [CHAR LIMIT=NONE] --> @@ -725,32 +725,14 @@ <!-- Description of the left direction in which one can to slide the handle in the Slide unlock screen. [CHAR LIMIT=NONE] --> <string name="description_direction_left">"Slide left for <xliff:g id="target_description" example="Unlock">%s</xliff:g>.</string> - <!-- Zen mode: No interruptions title, with a warning about alarms. [CHAR LIMIT=60] --> - <string name="zen_no_interruptions_with_warning">No interruptions. Not even alarms.</string> - <!-- Zen mode: Priority only introduction message on first use --> - <string name="zen_priority_introduction">You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events, and callers you specify.</string> + <string name="zen_priority_introduction">You won’t be disturbed by sounds and vibrations, except from alarms, reminders, events, and callers you specify.</string> <!-- Zen mode: Priority only customization button label --> <string name="zen_priority_customize_button">Customize</string> - <!-- Zen mode: No interruptions. [CHAR LIMIT=40] --> - <string name="zen_no_interruptions">No interruptions</string> - - <!-- Zen mode: Only important interruptions. [CHAR LIMIT=40] --> - <string name="zen_important_interruptions">Priority interruptions only</string> - - <!-- Zen mode: Only alarms. [CHAR LIMIT=40] --> - <string name="zen_alarms">Alarms only</string> - - <!-- Zen mode: Next alarm information - just a time. [CHAR LIMIT=40] --> - <string name="zen_alarm_information_time">Your next alarm is at <xliff:g id="alarm_time" example="5:00 PM">%s</xliff:g></string> - - <!-- Zen mode: Next alarm information - day and time. [CHAR LIMIT=40] --> - <string name="zen_alarm_information_day_time">Your next alarm is <xliff:g id="alarm_day_and_time" example="Fri 5:00 PM">%s</xliff:g></string> - - <!-- Zen mode: Next alarm warning. [CHAR LIMIT=40] --> - <string name="zen_alarm_warning">You won\'t hear your alarm at <xliff:g id="alarm_time" example="5:00 PM">%s</xliff:g></string> + <!-- Zen mode: Total silence introduction message on first use --> + <string name="zen_silence_introduction">This blocks ALL sounds and vibrations, including from alarms, music, videos, and games. You’ll still be able to make phone calls.</string> <!-- Text for overflow card on Keyguard when there is not enough space for all notifications on Keyguard. [CHAR LIMIT=1] --> <string name="keyguard_more_overflow_text">+<xliff:g id="number_of_notifications" example="5">%d</xliff:g></string> @@ -771,7 +753,7 @@ <string name="camera_hint">Swipe left for camera</string> <!-- Interruption level: None. [CHAR LIMIT=20] --> - <string name="interruption_level_none">No interruptions</string> + <string name="interruption_level_none">Total silence</string> <!-- Interruption level: Priority. [CHAR LIMIT=20] --> <string name="interruption_level_priority">Priority only</string> @@ -779,11 +761,8 @@ <!-- Interruption level: Alarms only. [CHAR LIMIT=20] --> <string name="interruption_level_alarms">Alarms only</string> - <!-- Interruption level: All. [CHAR LIMIT=20] --> - <string name="interruption_level_all">All</string> - <!-- Interruption level: None. Optimized for narrow two-line display. [CHAR LIMIT=20] --> - <string name="interruption_level_none_twoline">No\ninterruptions</string> + <string name="interruption_level_none_twoline">Total\nsilence</string> <!-- Interruption level: Priority. Optimized for narrow two-line display. [CHAR LIMIT=20] --> <string name="interruption_level_priority_twoline">Priority\nonly</string> @@ -953,6 +932,9 @@ <!-- Accessibility string for current zen mode and selected exit condition. A template that simply concatenates existing mode string and the current condition description. [CHAR LIMIT=20] --> <string name="zen_mode_and_condition"><xliff:g id="zen_mode" example="Priority interruptions only">%1$s</xliff:g>. <xliff:g id="exit_condition" example="For one hour">%2$s</xliff:g></string> + <!-- Button label for ending zen mode in the volume dialog --> + <string name="volume_zen_end_now">End now</string> + <!-- Screen pinning dialog title. --> <string name="screen_pinning_title">Screen is pinned</string> <!-- Screen pinning dialog description. --> @@ -988,9 +970,26 @@ <!-- VolumeUI restoration notification: text --> <string name="volumeui_notification_text">Touch to restore the original.</string> - <!-- Volume dialog zen toggle switch title --> - <string name="volume_zen_switch_text" translatable="false">@*android:string/zen_mode_feature_name</string> - <!-- Toast shown when user unlocks screen and managed profile activity is in the foreground --> <string name="managed_profile_foreground_toast">You are in the Work profile</string> + + <string-array name="volume_stream_titles" translatable="false"> + <item>Voice calls</item> <!-- STREAM_VOICE_CALL --> + <item>System</item> <!-- STREAM_SYSTEM --> + <item>Notifications</item> <!-- STREAM_RING --> + <item>Media</item> <!-- STREAM_MUSIC --> + <item>Alarms</item> <!-- STREAM_ALARM --> + <item></item> <!-- STREAM_NOTIFICATION --> + <item>Bluetooth calls</item> <!-- STREAM_BLUETOOTH_SCO --> + <item></item> <!-- STREAM_SYSTEM_ENFORCED --> + <item></item> <!-- STREAM_DTMF --> + <item></item> <!-- STREAM_TTS --> + </string-array> + + <string name="volume_stream_muted" translatable="false">%s silent</string> + <string name="volume_stream_vibrate" translatable="false">%s vibrate</string> + <string name="volume_stream_suppressed" translatable="false">%1$s silent — %2$s</string> + <string name="volume_stream_muted_dnd" translatable="false">%s silent — Total silence</string> + <string name="volume_stream_limited_dnd" translatable="false">%s — Priority only</string> + <string name="volume_stream_vibrate_dnd" translatable="false">%s vibrate — Priority only</string> </resources> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index ef2e6f35dd11..c058d445770a 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -165,7 +165,7 @@ </style> <style name="TextAppearance.QS.SegmentedButton"> - <item name="android:textSize">14sp</item> + <item name="android:textSize">16sp</item> </style> <style name="TextAppearance.QS.DataUsage"> @@ -262,4 +262,31 @@ <item name="fillColor">@color/dark_mode_icon_color_dual_tone_fill</item> <item name="singleToneColor">@color/dark_mode_icon_color_single_tone</item> </style> + + <style name="TextAppearance.Volume"> + <item name="android:textStyle">normal</item> + <item name="android:textColor">#ffffffff</item> + <item name="android:fontFamily">sans-serif</item> + </style> + + <style name="TextAppearance.Volume.ZenSummary"> + <item name="android:textSize">14sp</item> + <item name="android:fontFamily">sans-serif-medium</item> + </style> + + <style name="TextAppearance.Volume.ZenDetail"> + <item name="android:textSize">14sp</item> + <item name="android:fontFamily">sans-serif</item> + <item name="android:textColor">#ffb0b3c5</item> + </style> + + <style name="VolumeDialogAnimations"> + <item name="android:windowEnterAnimation">@android:anim/fade_in</item> + <item name="android:windowExitAnimation">@android:anim/fade_out</item> + </style> + + <style name="VolumeButtons" parent="@android:style/Widget.Material.Button.Borderless"> + <item name="android:background">@drawable/btn_borderless_rect</item> + </style> + </resources> diff --git a/packages/SystemUI/res/values/volume.xml b/packages/SystemUI/res/values/volume.xml deleted file mode 100644 index f516104306d8..000000000000 --- a/packages/SystemUI/res/values/volume.xml +++ /dev/null @@ -1,87 +0,0 @@ -<!-- - Copyright (C) 2015 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 xmlns:android="http://schemas.android.com/apk/res/android"> - - <item name="volume_expand_animation_duration" type="integer">300</item> - - <color name="volume_icon_color">#ffffffff</color> - <color name="volume_settings_icon_color">#7fffffff</color> - - <dimen name="volume_slider_interspacing">2dp</dimen> - <dimen name="volume_offset_top">0dp</dimen> - <dimen name="volume_button_size">48dp</dimen> - - <item name="volume_secondary_alpha" format="float" type="dimen">0.3</item> - - <style name="VolumeDialogAnimations"> - <item name="android:windowEnterAnimation">@android:anim/fade_in</item> - <item name="android:windowExitAnimation">@android:anim/fade_out</item> - </style> - - <style name="VolumeButtons" parent="@android:style/Widget.Material.Button.Borderless"> - <item name="android:background">@drawable/btn_borderless_rect</item> - </style> - - <style name="TextAppearance" /> - - <style name="TextAppearance.Volume"> - <item name="android:textStyle">normal</item> - <item name="android:textColor">#ffffffff</item> - <item name="android:fontFamily">sans-serif</item> - </style> - - <style name="TextAppearance.Volume.ZenSwitch"> - <item name="android:textSize">16sp</item> - <item name="android:fontFamily">sans-serif-medium</item> - </style> - - <style name="TextAppearance.Volume.ZenSwitchSummary"> - <item name="android:textSize">14sp</item> - <item name="android:fontFamily">sans-serif-medium</item> - </style> - - <style name="TextAppearance.Volume.ZenSwitchDetail"> - <item name="android:textSize">14sp</item> - <item name="android:fontFamily">sans-serif</item> - <item name="android:textColor">#ffb0b3c5</item> - </style> - - <string-array name="volume_stream_titles" translatable="false"> - <item>Voice calls</item> <!-- STREAM_VOICE_CALL --> - <item>System</item> <!-- STREAM_SYSTEM --> - <item>Notifications</item> <!-- STREAM_RING --> - <item>Media</item> <!-- STREAM_MUSIC --> - <item>Alarms</item> <!-- STREAM_ALARM --> - <item></item> <!-- STREAM_NOTIFICATION --> - <item>Bluetooth calls</item> <!-- STREAM_BLUETOOTH_SCO --> - <item></item> <!-- STREAM_SYSTEM_ENFORCED --> - <item></item> <!-- STREAM_DTMF --> - <item></item> <!-- STREAM_TTS --> - </string-array> - - <string name="volume_dnd_is_on" translatable="false">Do not disturb is on</string> - <string name="volume_turn_off" translatable="false">Turn off</string> - <string name="volume_stream_muted" translatable="false">%s silent</string> - <string name="volume_stream_vibrate" translatable="false">%s vibrate</string> - <string name="volume_stream_suppressed" translatable="false">%1$s silent — %2$s</string> - <string name="volume_stream_muted_dnd" translatable="false">%s silent — No interruptions</string> - <string name="volume_stream_limited_dnd" translatable="false">%s — Priority only</string> - <string name="volume_stream_vibrate_dnd" translatable="false">%s vibrate — Priority only</string> - <string name="volume_dnd_ends_in" translatable="false">Do not disturb ends in %s</string> - <string name="volume_dnd_ends_at" translatable="false">Do not disturb ends at %s</string> - <string name="volume_end_now" translatable="false">End now</string> - -</resources>
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java index 68b196847838..29d2a014133e 100644 --- a/packages/SystemUI/src/com/android/systemui/Prefs.java +++ b/packages/SystemUI/src/com/android/systemui/Prefs.java @@ -37,8 +37,10 @@ public final class Prefs { Key.DND_TILE_VISIBLE, Key.DND_TILE_COMBINED_ICON, Key.DND_CONFIRMED_PRIORITY_INTRODUCTION, + Key.DND_CONFIRMED_SILENCE_INTRODUCTION, Key.DND_FAVORITE_BUCKET_INDEX, Key.DND_NONE_SELECTED, + Key.DND_FAVORITE_ZEN, }) public @interface Key { String SEARCH_APP_WIDGET_ID = "searchAppWidgetId"; @@ -48,8 +50,10 @@ public final class Prefs { String DND_TILE_VISIBLE = "DndTileVisible"; String DND_TILE_COMBINED_ICON = "DndTileCombinedIcon"; String DND_CONFIRMED_PRIORITY_INTRODUCTION = "DndConfirmedPriorityIntroduction"; + String DND_CONFIRMED_SILENCE_INTRODUCTION = "DndConfirmedSilenceIntroduction"; String DND_FAVORITE_BUCKET_INDEX = "DndCountdownMinuteIndex"; String DND_NONE_SELECTED = "DndNoneSelected"; + String DND_FAVORITE_ZEN = "DndFavoriteZen"; } public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 40b867ccfaa5..6479dc500643 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -1398,14 +1398,9 @@ public class KeyguardViewMediator extends SystemUI { updateActivityLockScreenState(); adjustStatusBarLocked(); sendUserPresentBroadcast(); - maybeStopListeningForFingerprint(); } } - private void maybeStopListeningForFingerprint() { - mUpdateMonitor.stopListeningForFingerprint(); - } - private void adjustStatusBarLocked() { if (mStatusBarManager == null) { mStatusBarManager = (StatusBarManager) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index 6ce63d66a1c6..5145bc7cc37d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -37,7 +37,11 @@ import com.android.systemui.volume.ZenModePanel; /** Quick settings tile: Do not disturb **/ public class DndTile extends QSTile<QSTile.BooleanState> { - private static final Intent ZEN_SETTINGS = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS); + private static final Intent ZEN_SETTINGS = + new Intent(Settings.ACTION_ZEN_MODE_SETTINGS); + + private static final Intent ZEN_PRIORITY_SETTINGS = + new Intent(Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS); private static final String ACTION_SET_VISIBLE = "com.android.systemui.dndtile.SET_VISIBLE"; private static final String EXTRA_VISIBLE = "visible"; @@ -87,7 +91,9 @@ public class DndTile extends QSTile<QSTile.BooleanState> { if (mState.value) { mController.setZen(Global.ZEN_MODE_OFF, null, TAG); } else { - mController.setZen(Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG); + int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS); + mController.setZen(zen, null, TAG); + refreshState(zen); // this one's optimistic showDetail(true); } } @@ -209,8 +215,8 @@ public class DndTile extends QSTile<QSTile.BooleanState> { R.layout.zen_mode_panel, parent, false); if (convertView == null) { zmp.init(mController); - zmp.setEmbedded(true); zmp.addOnAttachStateChangeListener(this); + zmp.setCallback(mZenModePanelCallback); } return zmp; } @@ -225,4 +231,22 @@ public class DndTile extends QSTile<QSTile.BooleanState> { mShowingDetail = false; } } + + private final ZenModePanel.Callback mZenModePanelCallback = new ZenModePanel.Callback() { + @Override + public void onPrioritySettings() { + mHost.startSettingsActivity(ZEN_PRIORITY_SETTINGS); + } + + @Override + public void onInteraction() { + // noop + } + + @Override + public void onExpanded(boolean expanded) { + // noop + } + }; + } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 8050ea0aa511..26c3b4ef6e4d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -784,7 +784,8 @@ public abstract class BaseStatusBar extends SystemUI implements protected void applyColorsAndBackgrounds(StatusBarNotification sbn, NotificationData.Entry entry) { - if (entry.expanded.getId() != com.android.internal.R.id.status_bar_latest_event_content) { + if (entry.getContentView().getId() + != com.android.internal.R.id.status_bar_latest_event_content) { // Using custom RemoteViews if (entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD && entry.targetSdk < Build.VERSION_CODES.LOLLIPOP) { @@ -809,8 +810,9 @@ public abstract class BaseStatusBar extends SystemUI implements public boolean isMediaNotification(NotificationData.Entry entry) { // TODO: confirm that there's a valid media key - return entry.expandedBig != null && - entry.expandedBig.findViewById(com.android.internal.R.id.media_actions) != null; + return entry.getExpandedContentView() != null && + entry.getExpandedContentView() + .findViewById(com.android.internal.R.id.media_actions) != null; } // The gear button in the guts that links to the app's own notification settings @@ -1134,9 +1136,9 @@ public abstract class BaseStatusBar extends SystemUI implements } /** - * if the interrupting notification had a fullscreen intent, fire it now. + * If there is an active heads-up notification and it has a fullscreen intent, fire it now. */ - public abstract void escalateHeadsUp(); + public abstract void maybeEscalateHeadsUp(); /** * Save the current "public" (locked and secure) state of the lockscreen. @@ -1337,8 +1339,8 @@ public abstract class BaseStatusBar extends SystemUI implements View publicViewLocal = null; if (publicNotification != null) { try { - publicViewLocal = publicNotification.contentView.apply(mContext, contentContainerPublic, - mOnClickHandler); + publicViewLocal = publicNotification.contentView.apply(mContext, + contentContainerPublic, mOnClickHandler); if (publicViewLocal != null) { publicViewLocal.setIsRootNamespace(true); @@ -1445,9 +1447,7 @@ public abstract class BaseStatusBar extends SystemUI implements entry.row = row; entry.row.setHeightRange(mRowMinHeight, maxHeight); entry.row.setOnActivatedListener(this); - entry.expanded = contentViewLocal; - entry.expandedPublic = publicViewLocal; - entry.setBigContentView(bigContentViewLocal); + entry.row.setExpandable(bigContentViewLocal != null); applyColorsAndBackgrounds(sbn, entry); @@ -1536,12 +1536,13 @@ public abstract class BaseStatusBar extends SystemUI implements // See if we have somewhere to put that remote input if (remoteInput != null) { - if (entry.expandedBig != null) { - inflateRemoteInput(entry.expandedBig, remoteInput, actions); + View bigContentView = entry.getExpandedContentView(); + if (bigContentView != null) { + inflateRemoteInput(bigContentView, remoteInput, actions); } - View headsUpChild = entry.row.getPrivateLayout().getHeadsUpChild(); - if (headsUpChild != null) { - inflateRemoteInput(headsUpChild, remoteInput, actions); + View headsUpContentView = entry.getHeadsUpContentView(); + if (headsUpContentView != null) { + inflateRemoteInput(headsUpContentView, remoteInput, actions); } } @@ -1883,15 +1884,14 @@ public abstract class BaseStatusBar extends SystemUI implements logUpdate(entry, n); } boolean applyInPlace = shouldApplyInPlace(entry, n); - final boolean shouldInterrupt = shouldInterrupt(notification); - final boolean alertAgain = alertAgain(entry, n); + boolean shouldInterrupt = shouldInterrupt(notification); + boolean alertAgain = alertAgain(entry, n); entry.notification = notification; mGroupManager.onEntryUpdated(entry, entry.notification); boolean updateSuccessful = false; if (applyInPlace) { - // We can just reapply the notifications in place if (DEBUG) Log.d(TAG, "reusing notification for key: " + key); try { if (entry.icon != null) { @@ -1912,7 +1912,7 @@ public abstract class BaseStatusBar extends SystemUI implements updateSuccessful = true; } catch (RuntimeException e) { - // It failed to add cleanly. Log, and remove the view from the panel. + // It failed to apply cleanly. Log.w(TAG, "Couldn't reapply views for package " + n.contentView.getPackage(), e); } } @@ -1936,11 +1936,12 @@ public abstract class BaseStatusBar extends SystemUI implements // swipe-dismissable) updateNotificationVetoButton(entry.row, notification); - // Is this for you? - boolean isForCurrentUser = isNotificationForCurrentProfiles(notification); - if (DEBUG) Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you"); + if (DEBUG) { + // Is this for you? + boolean isForCurrentUser = isNotificationForCurrentProfiles(notification); + Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you"); + } - // Recalculate the position of the sliding windows and the titles. setAreThereNotifications(); } @@ -1951,7 +1952,7 @@ public abstract class BaseStatusBar extends SystemUI implements StatusBarNotification oldNotification = oldEntry.notification; Log.d(TAG, "old notification: when=" + oldNotification.getNotification().when + " ongoing=" + oldNotification.isOngoing() - + " expanded=" + oldEntry.expanded + + " expanded=" + oldEntry.getContentView() + " contentView=" + oldNotification.getNotification().contentView + " bigContentView=" + oldNotification.getNotification().bigContentView + " publicView=" + oldNotification.getNotification().publicVersion @@ -1964,7 +1965,8 @@ public abstract class BaseStatusBar extends SystemUI implements } /** - * @return whether we can just reapply the RemoteViews in place when it is updated + * @return whether we can just reapply the RemoteViews from a notification in-place when it is + * updated */ private boolean shouldApplyInPlace(Entry entry, Notification n) { StatusBarNotification oldNotification = entry.notification; @@ -1982,15 +1984,15 @@ public abstract class BaseStatusBar extends SystemUI implements final Notification publicNotification = n.publicVersion; final RemoteViews publicContentView = publicNotification != null ? publicNotification.contentView : null; - boolean contentsUnchanged = entry.expanded != null + boolean contentsUnchanged = entry.getContentView() != null && contentView.getPackage() != null && oldContentView.getPackage() != null && oldContentView.getPackage().equals(contentView.getPackage()) && oldContentView.getLayoutId() == contentView.getLayoutId(); // large view may be null boolean bigContentsUnchanged = - (entry.getBigContentView() == null && bigContentView == null) - || ((entry.getBigContentView() != null && bigContentView != null) + (entry.getExpandedContentView() == null && bigContentView == null) + || ((entry.getExpandedContentView() != null && bigContentView != null) && bigContentView.getPackage() != null && oldBigContentView.getPackage() != null && oldBigContentView.getPackage().equals(bigContentView.getPackage()) @@ -2022,12 +2024,12 @@ public abstract class BaseStatusBar extends SystemUI implements : null; // Reapply the RemoteViews - contentView.reapply(mContext, entry.expanded, mOnClickHandler); - if (bigContentView != null && entry.getBigContentView() != null) { - bigContentView.reapply(mContext, entry.getBigContentView(), + contentView.reapply(mContext, entry.getContentView(), mOnClickHandler); + if (bigContentView != null && entry.getExpandedContentView() != null) { + bigContentView.reapply(mContext, entry.getExpandedContentView(), mOnClickHandler); } - View headsUpChild = entry.row.getPrivateLayout().getHeadsUpChild(); + View headsUpChild = entry.getHeadsUpContentView(); if (headsUpContentView != null && headsUpChild != null) { headsUpContentView.reapply(mContext, headsUpChild, mOnClickHandler); } @@ -2050,7 +2052,7 @@ public abstract class BaseStatusBar extends SystemUI implements } protected void notifyHeadsUpScreenOff() { - escalateHeadsUp(); + maybeEscalateHeadsUp(); } private boolean alertAgain(Entry oldEntry, Notification newNotification) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index cb8217e26f2f..9ef495de0b46 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -84,7 +84,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { private ExpansionLogger mLogger; private String mLoggingKey; private boolean mWasReset; - private NotificationGuts mGuts; private StatusBarNotification mStatusBarNotification; private boolean mIsHeadsUp; @@ -102,6 +101,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { private ViewStub mGutsStub; private boolean mHasExpandAction; private boolean mIsSystemChildExpanded; + private boolean mIsPinned; private OnClickListener mExpandClickListener = new OnClickListener() { @Override public void onClick(View v) { @@ -109,7 +109,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { !mChildrenExpanded); } }; - private boolean mInShade; public NotificationContentView getPrivateLayout() { return mPrivateLayout; @@ -284,12 +283,18 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { return realActualHeight; } - public void setInShade(boolean inShade) { - mInShade = inShade; + /** + * Set this notification to be pinned to the top if {@link #isHeadsUp()} is true. By doing this + * the notification will be rendered on top of the screen. + * + * @param pinned whether it is pinned + */ + public void setPinned(boolean pinned) { + mIsPinned = pinned; } - public boolean isInShade() { - return mInShade; + public boolean isPinned() { + return mIsPinned; } public int getHeadsUpHeight() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java index 1c53655a1226..110b14c40a9f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java @@ -32,37 +32,34 @@ import android.widget.FrameLayout; import com.android.systemui.R; /** - * A frame layout containing the actual payload of the notification, including the contracted and - * expanded layout. This class is responsible for clipping the content and and switching between the - * expanded and contracted view depending on its clipped size. + * A frame layout containing the actual payload of the notification, including the contracted, + * expanded and heads up layout. This class is responsible for clipping the content and and + * switching between the expanded, contracted and the heads up view depending on its clipped size. */ public class NotificationContentView extends FrameLayout { private static final long ANIMATION_DURATION_LENGTH = 170; - private static final int CONTRACTED = 1; - private static final int EXPANDED = 2; - private static final int HEADSUP = 3; + private static final int VISIBLE_TYPE_CONTRACTED = 0; + private static final int VISIBLE_TYPE_EXPANDED = 1; + private static final int VISIBLE_TYPE_HEADSUP = 2; private final Rect mClipBounds = new Rect(); + private final int mSmallHeight; + private final int mHeadsUpHeight; + private final Interpolator mLinearInterpolator = new LinearInterpolator(); private View mContractedChild; private View mExpandedChild; private View mHeadsUpChild; private NotificationViewWrapper mContractedWrapper; - - private final int mSmallHeight; - private final int mHeadsUpHeight; private int mClipTopAmount; - private int mContentHeight; - - private final Interpolator mLinearInterpolator = new LinearInterpolator(); - private int mVisibleView = CONTRACTED; - + private int mVisibleType = VISIBLE_TYPE_CONTRACTED; private boolean mDark; private final Paint mFadePaint = new Paint(); private boolean mAnimate; + private boolean mIsHeadsUp; private ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener = new ViewTreeObserver.OnPreDrawListener() { @Override @@ -72,7 +69,6 @@ public class NotificationContentView extends FrameLayout { return true; } }; - private boolean mIsHeadsUp; public NotificationContentView(Context context, AttributeSet attrs) { super(context, attrs); @@ -105,9 +101,9 @@ public class NotificationContentView extends FrameLayout { // An actual height is set size = Math.min(maxSize, layoutParams.height); } - int spec = size == Integer.MAX_VALUE ? - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED) : - MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST); + int spec = size == Integer.MAX_VALUE + ? MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED) + : MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST); mExpandedChild.measure(widthMeasureSpec, spec); maxChildHeight = Math.max(maxChildHeight, mExpandedChild.getMeasuredHeight()); } @@ -153,7 +149,7 @@ public class NotificationContentView extends FrameLayout { mContractedChild = null; mExpandedChild = null; mHeadsUpChild = null; - mVisibleView = CONTRACTED; + mVisibleType = VISIBLE_TYPE_CONTRACTED; if (resetActualHeight) { mContentHeight = mSmallHeight; } @@ -263,30 +259,32 @@ public class NotificationContentView extends FrameLayout { if (mContractedChild == null) { return; } - int visibleView = calculateVisibleView(); - if (visibleView != mVisibleView || force) { - if (animate && mExpandedChild != null) { - runSwitchAnimation(visibleView); + int visibleType = calculateVisibleType(); + if (visibleType != mVisibleType || force) { + if (animate && (visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null) + || (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null) + || visibleType == VISIBLE_TYPE_CONTRACTED) { + runSwitchAnimation(visibleType); } else { - updateViewVisibilities(visibleView); + updateViewVisibilities(visibleType); } - mVisibleView = visibleView; + mVisibleType = visibleType; } } - private void updateViewVisibilities(int visibleView) { - boolean contractedVisible = visibleView == CONTRACTED; + private void updateViewVisibilities(int visibleType) { + boolean contractedVisible = visibleType == VISIBLE_TYPE_CONTRACTED; mContractedChild.setVisibility(contractedVisible ? View.VISIBLE : View.INVISIBLE); mContractedChild.setAlpha(contractedVisible ? 1f : 0f); mContractedChild.setLayerType(LAYER_TYPE_NONE, null); if (mExpandedChild != null) { - boolean expandedVisible = visibleView == EXPANDED; + boolean expandedVisible = visibleType == VISIBLE_TYPE_EXPANDED; mExpandedChild.setVisibility(expandedVisible ? View.VISIBLE : View.INVISIBLE); mExpandedChild.setAlpha(expandedVisible ? 1f : 0f); mExpandedChild.setLayerType(LAYER_TYPE_NONE, null); } if (mHeadsUpChild != null) { - boolean headsUpVisible = visibleView == HEADSUP; + boolean headsUpVisible = visibleType == VISIBLE_TYPE_HEADSUP; mHeadsUpChild.setVisibility(headsUpVisible ? View.VISIBLE : View.INVISIBLE); mHeadsUpChild.setAlpha(headsUpVisible ? 1f : 0f); mHeadsUpChild.setLayerType(LAYER_TYPE_NONE, null); @@ -294,9 +292,9 @@ public class NotificationContentView extends FrameLayout { setLayerType(LAYER_TYPE_NONE, null); } - private void runSwitchAnimation(int visibleView) { - View shownView = getViewFromFlag(visibleView); - View hiddenView = getViewFromFlag(mVisibleView); + private void runSwitchAnimation(int visibleType) { + View shownView = getViewForVisibleType(visibleType); + View hiddenView = getViewForVisibleType(mVisibleType); shownView.setVisibility(View.VISIBLE); hiddenView.setVisibility(View.VISIBLE); shownView.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint); @@ -314,34 +312,42 @@ public class NotificationContentView extends FrameLayout { .withEndAction(new Runnable() { @Override public void run() { - updateViewVisibilities(mVisibleView); + updateViewVisibilities(mVisibleType); } }); } - private View getViewFromFlag(int visibleView) { - switch (visibleView) { - case EXPANDED: + /** + * @param visibleType one of the static enum types in this view + * @return the corresponding view according to the given visible type + */ + private View getViewForVisibleType(int visibleType) { + switch (visibleType) { + case VISIBLE_TYPE_EXPANDED: return mExpandedChild; - case HEADSUP: + case VISIBLE_TYPE_HEADSUP: return mHeadsUpChild; + default: + return mContractedChild; } - return mContractedChild; } - private int calculateVisibleView() { + /** + * @return one of the static enum types in this view, calculated form the current state + */ + private int calculateVisibleType() { boolean noExpandedChild = mExpandedChild == null; if (mIsHeadsUp && mHeadsUpChild != null) { if (mContentHeight <= mHeadsUpChild.getHeight() || noExpandedChild) { - return HEADSUP; + return VISIBLE_TYPE_HEADSUP; } else { - return EXPANDED; + return VISIBLE_TYPE_EXPANDED; } } else { if (mContentHeight <= mSmallHeight || noExpandedChild) { - return CONTRACTED; + return VISIBLE_TYPE_CONTRACTED; } else { - return EXPANDED; + return VISIBLE_TYPE_EXPANDED; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java index 429889d97bd9..2a8b4acc70e0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java @@ -45,9 +45,6 @@ public class NotificationData { public StatusBarNotification notification; public StatusBarIconView icon; public ExpandableNotificationRow row; // the outer expanded view - public View expanded; // the inflated RemoteViews - public View expandedPublic; // for insecure lockscreens - public View expandedBig; private boolean interruption; public boolean autoRedacted; // whether the redacted notification was generated by us public boolean legacy; // whether the notification has a legacy, dark background @@ -58,14 +55,6 @@ public class NotificationData { this.notification = n; this.icon = ic; } - public void setBigContentView(View bigContentView) { - this.expandedBig = bigContentView; - row.setExpandable(bigContentView != null); - } - public View getBigContentView() { - return expandedBig; - } - public View getPublicContentView() { return expandedPublic; } public void setInterruption() { interruption = true; @@ -81,15 +70,28 @@ public class NotificationData { public void reset() { // NOTE: Icon needs to be preserved for now. // We should fix this at some point. - expanded = null; - expandedPublic = null; - expandedBig = null; autoRedacted = false; legacy = false; if (row != null) { row.reset(); } } + + public View getContentView() { + return row.getPrivateLayout().getContractedChild(); + } + + public View getExpandedContentView() { + return row.getPrivateLayout().getExpandedChild(); + } + + public View getHeadsUpContentView() { + return row.getPrivateLayout().getHeadsUpChild(); + } + + public View getPublicContentView() { + return row.getPublicLayout().getContractedChild(); + } } private final ArrayMap<String, Entry> mEntries = new ArrayMap<>(); @@ -258,7 +260,7 @@ public class NotificationData { */ public boolean hasActiveClearableNotifications() { for (Entry e : mSortedAndFiltered) { - if (e.expanded != null) { // the view successfully inflated + if (e.getContentView() != null) { // the view successfully inflated if (e.notification.isClearable()) { return true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java index 399780776f20..fe7bc977f3fd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java @@ -27,7 +27,7 @@ import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; /** - * A Helper class to handle touches on the heads-up views + * A helper class to handle touches on the heads-up views. */ public class HeadsUpTouchHelper implements Gefingerpoken { @@ -37,19 +37,30 @@ public class HeadsUpTouchHelper implements Gefingerpoken { private float mTouchSlop; private float mInitialTouchX; private float mInitialTouchY; - private boolean mMotionOnHeadsUpView; + private boolean mTouchingHeadsUpView; private boolean mTrackingHeadsUp; private boolean mCollapseSnoozes; private NotificationPanelView mPanel; private ExpandableNotificationRow mPickedChild; + public HeadsUpTouchHelper(HeadsUpManager headsUpManager, + NotificationStackScrollLayout stackScroller, + NotificationPanelView notificationPanelView) { + mHeadsUpManager = headsUpManager; + mStackScroller = stackScroller; + mPanel = notificationPanelView; + Context context = stackScroller.getContext(); + final ViewConfiguration configuration = ViewConfiguration.get(context); + mTouchSlop = configuration.getScaledTouchSlop(); + } + public boolean isTrackingHeadsUp() { return mTrackingHeadsUp; } @Override public boolean onInterceptTouchEvent(MotionEvent event) { - if (!mMotionOnHeadsUpView && event.getActionMasked() != MotionEvent.ACTION_DOWN) { + if (!mTouchingHeadsUpView && event.getActionMasked() != MotionEvent.ACTION_DOWN) { return false; } int pointerIndex = event.findPointerIndex(mTrackingPointer); @@ -65,10 +76,10 @@ public class HeadsUpTouchHelper implements Gefingerpoken { mInitialTouchX = x; setTrackingHeadsUp(false); ExpandableView child = mStackScroller.getChildAtPosition(x, y); - mMotionOnHeadsUpView = false; + mTouchingHeadsUpView = false; if (child instanceof ExpandableNotificationRow) { mPickedChild = (ExpandableNotificationRow) child; - mMotionOnHeadsUpView = mPickedChild.isHeadsUp() && !mPickedChild.isInShade(); + mTouchingHeadsUpView = mPickedChild.isHeadsUp() && mPickedChild.isPinned(); } break; case MotionEvent.ACTION_POINTER_UP: @@ -97,7 +108,8 @@ public class HeadsUpTouchHelper implements Gefingerpoken { case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: - if (mPickedChild != null && mMotionOnHeadsUpView) { + if (mPickedChild != null && mTouchingHeadsUpView) { + // We may swallow this click if the heads up just came in. if (mHeadsUpManager.shouldSwallowClick( mPickedChild.getStatusBarNotification().getKey())) { endMotion(); @@ -141,20 +153,6 @@ public class HeadsUpTouchHelper implements Gefingerpoken { private void endMotion() { mTrackingPointer = -1; mPickedChild = null; - mMotionOnHeadsUpView = false; - } - - public ExpandableView getPickedChild() { - return mPickedChild; - } - - public void bind(HeadsUpManager headsUpManager, NotificationStackScrollLayout stackScroller, - NotificationPanelView notificationPanelView) { - mHeadsUpManager = headsUpManager; - mStackScroller = stackScroller; - mPanel = notificationPanelView; - Context context = stackScroller.getContext(); - final ViewConfiguration configuration = ViewConfiguration.get(context); - mTouchSlop = configuration.getScaledTouchSlop(); + mTouchingHeadsUpView = false; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 8099de8350a1..fabc1a6930c3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -86,7 +86,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private KeyguardAffordanceView mCameraImageView; private KeyguardAffordanceView mPhoneImageView; - private KeyguardAffordanceView mLockIcon; + private LockIcon mLockIcon; private TextView mIndicationText; private ViewGroup mPreviewContainer; @@ -102,11 +102,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private AccessibilityController mAccessibilityController; private PhoneStatusBar mPhoneStatusBar; - private final TrustDrawable mTrustDrawable; private final Interpolator mLinearOutSlowInInterpolator; - private int mLastUnlockIconRes = 0; private boolean mPrewarmSent; - private boolean mTransientFpError; public KeyguardBottomAreaView(Context context) { this(context, null); @@ -123,7 +120,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - mTrustDrawable = new TrustDrawable(mContext); mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in); } @@ -169,20 +165,19 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mPreviewContainer = (ViewGroup) findViewById(R.id.preview_container); mCameraImageView = (KeyguardAffordanceView) findViewById(R.id.camera_button); mPhoneImageView = (KeyguardAffordanceView) findViewById(R.id.phone_button); - mLockIcon = (KeyguardAffordanceView) findViewById(R.id.lock_icon); + mLockIcon = (LockIcon) findViewById(R.id.lock_icon); mIndicationText = (TextView) findViewById(R.id.keyguard_indication_text); watchForCameraPolicyChanges(); updateCameraVisibility(); updatePhoneVisibility(); mUnlockMethodCache = UnlockMethodCache.getInstance(getContext()); mUnlockMethodCache.addListener(this); - updateLockIcon(); + mLockIcon.update(); setClipChildren(false); setClipToPadding(false); mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext)); inflatePreviews(); mLockIcon.setOnClickListener(this); - mLockIcon.setBackground(mTrustDrawable); mLockIcon.setOnLongClickListener(this); mCameraImageView.setOnClickListener(this); mPhoneImageView.setOnClickListener(this); @@ -222,6 +217,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL public void setAccessibilityController(AccessibilityController accessibilityController) { mAccessibilityController = accessibilityController; + mLockIcon.setAccessibilityController(accessibilityController); accessibilityController.addStateChangedCallback(this); } @@ -294,21 +290,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mPhoneImageView.setClickable(touchExplorationEnabled); mCameraImageView.setFocusable(accessibilityEnabled); mPhoneImageView.setFocusable(accessibilityEnabled); - updateLockIconClickability(); - } - - private void updateLockIconClickability() { - if (mAccessibilityController == null) { - return; - } - boolean clickToUnlock = mAccessibilityController.isTouchExplorationEnabled(); - boolean clickToForceLock = mUnlockMethodCache.isTrustManaged() - && !mAccessibilityController.isAccessibilityEnabled(); - boolean longClickToForceLock = mUnlockMethodCache.isTrustManaged() - && !clickToForceLock; - mLockIcon.setClickable(clickToForceLock || clickToUnlock); - mLockIcon.setLongClickable(longClickToForceLock); - mLockIcon.setFocusable(mAccessibilityController.isAccessibilityEnabled()); + mLockIcon.update(); } @Override @@ -409,69 +391,12 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL @Override protected void onVisibilityChanged(View changedView, int visibility) { super.onVisibilityChanged(changedView, visibility); - if (isShown()) { - mTrustDrawable.start(); - } else { - mTrustDrawable.stop(); - } if (changedView == this && visibility == VISIBLE) { - updateLockIcon(); + mLockIcon.update(); updateCameraVisibility(); } } - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - mTrustDrawable.stop(); - } - - private void updateLockIcon() { - boolean visible = isShown() && KeyguardUpdateMonitor.getInstance(mContext).isScreenOn(); - if (visible) { - mTrustDrawable.start(); - } else { - mTrustDrawable.stop(); - } - if (!visible) { - return; - } - // TODO: Real icon for facelock. - boolean isFingerprintIcon = - KeyguardUpdateMonitor.getInstance(mContext).isFingerprintDetectionRunning(); - boolean anyFingerprintIcon = isFingerprintIcon || mTransientFpError; - int iconRes = mTransientFpError ? R.drawable.ic_fingerprint_error - : isFingerprintIcon ? R.drawable.ic_fingerprint - : mUnlockMethodCache.isFaceUnlockRunning() - ? com.android.internal.R.drawable.ic_account_circle - : mUnlockMethodCache.isCurrentlyInsecure() ? R.drawable.ic_lock_open_24dp - : R.drawable.ic_lock_24dp; - - if (mLastUnlockIconRes != iconRes) { - Drawable icon = mContext.getDrawable(iconRes); - int iconHeight = getResources().getDimensionPixelSize( - R.dimen.keyguard_affordance_icon_height); - int iconWidth = getResources().getDimensionPixelSize( - R.dimen.keyguard_affordance_icon_width); - if (!anyFingerprintIcon && (icon.getIntrinsicHeight() != iconHeight - || icon.getIntrinsicWidth() != iconWidth)) { - icon = new IntrinsicSizeDrawable(icon, iconWidth, iconHeight); - } - mLockIcon.setImageDrawable(icon); - mLockIcon.setPaddingRelative(0, 0, 0, anyFingerprintIcon - ? getResources().getDimensionPixelSize( - R.dimen.fingerprint_icon_additional_padding) - : 0); - mLockIcon.setRestingAlpha( - anyFingerprintIcon ? 1f : KeyguardAffordanceHelper.SWIPE_RESTING_ALPHA_AMOUNT); - } - - // Hide trust circle when fingerprint is running. - boolean trustManaged = mUnlockMethodCache.isTrustManaged() && !anyFingerprintIcon; - mTrustDrawable.setTrustManaged(trustManaged); - updateLockIconClickability(); - } - public KeyguardAffordanceView getPhoneView() { return mPhoneImageView; } @@ -503,7 +428,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL @Override public void onUnlockMethodStateChanged() { - updateLockIcon(); + mLockIcon.update(); updateCameraVisibility(); } @@ -563,9 +488,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private final Runnable mTransientFpErrorClearRunnable = new Runnable() { @Override public void run() { - mTransientFpError = false; + mLockIcon.setTransientFpError(false); mIndicationController.hideTransientIndication(); - updateLockIcon(); } }; @@ -578,17 +502,17 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL @Override public void onScreenTurnedOn() { - updateLockIcon(); + mLockIcon.update(); } @Override public void onScreenTurnedOff(int why) { - updateLockIcon(); + mLockIcon.update(); } @Override public void onKeyguardVisibilityChanged(boolean showing) { - updateLockIcon(); + mLockIcon.update(); } @Override @@ -597,24 +521,21 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL @Override public void onFingerprintRunningStateChanged(boolean running) { - updateLockIcon(); + mLockIcon.update(); } @Override public void onFingerprintHelp(int msgId, String helpString) { - mTransientFpError = true; + mLockIcon.setTransientFpError(true); mIndicationController.showTransientIndication(helpString, getResources().getColor(R.color.system_warning_color, null)); removeCallbacks(mTransientFpErrorClearRunnable); postDelayed(mTransientFpErrorClearRunnable, TRANSIENT_FP_ERROR_TIMEOUT); - updateLockIcon(); } @Override public void onFingerprintError(int msgId, String errString) { // TODO: Go to bouncer if this is "too many attempts" (lockout) error. - Log.i(TAG, "FP Error: " + errString); - updateLockIcon(); } }; @@ -622,29 +543,4 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL KeyguardIndicationController keyguardIndicationController) { mIndicationController = keyguardIndicationController; } - - /** - * A wrapper around another Drawable that overrides the intrinsic size. - */ - private static class IntrinsicSizeDrawable extends InsetDrawable { - - private final int mIntrinsicWidth; - private final int mIntrinsicHeight; - - public IntrinsicSizeDrawable(Drawable drawable, int intrinsicWidth, int intrinsicHeight) { - super(drawable, 0); - mIntrinsicWidth = intrinsicWidth; - mIntrinsicHeight = intrinsicHeight; - } - - @Override - public int getIntrinsicWidth() { - return mIntrinsicWidth; - } - - @Override - public int getIntrinsicHeight() { - return mIntrinsicHeight; - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java new file mode 100644 index 000000000000..66f3232b8bbc --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2015 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.phone; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.graphics.drawable.AnimatedVectorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.InsetDrawable; +import android.util.AttributeSet; +import android.view.View; + +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.systemui.R; +import com.android.systemui.statusbar.KeyguardAffordanceView; +import com.android.systemui.statusbar.policy.AccessibilityController; + +/** + * Manages the different states and animations of the unlock icon. + */ +public class LockIcon extends KeyguardAffordanceView { + + + private static final int STATE_LOCKED = 0; + private static final int STATE_LOCK_OPEN = 1; + private static final int STATE_FACE_UNLOCK = 2; + private static final int STATE_FINGERPRINT = 3; + private static final int STATE_FINGERPRINT_ERROR = 4; + + private int mLastState = 0; + private boolean mTransientFpError; + private final TrustDrawable mTrustDrawable; + private final UnlockMethodCache mUnlockMethodCache; + private AccessibilityController mAccessibilityController; + + public LockIcon(Context context, AttributeSet attrs) { + super(context, attrs); + mTrustDrawable = new TrustDrawable(context); + setBackground(mTrustDrawable); + mUnlockMethodCache = UnlockMethodCache.getInstance(context); + } + + @Override + protected void onVisibilityChanged(View changedView, int visibility) { + super.onVisibilityChanged(changedView, visibility); + if (isShown()) { + mTrustDrawable.start(); + } else { + mTrustDrawable.stop(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mTrustDrawable.stop(); + } + + public void setTransientFpError(boolean transientFpError) { + mTransientFpError = transientFpError; + update(); + } + + public void update() { + boolean visible = isShown() && KeyguardUpdateMonitor.getInstance(mContext).isScreenOn(); + if (visible) { + mTrustDrawable.start(); + } else { + mTrustDrawable.stop(); + } + if (!visible) { + return; + } + // TODO: Real icon for facelock. + int state = getState(); + boolean anyFingerprintIcon = state == STATE_FINGERPRINT || state == STATE_FINGERPRINT_ERROR; + if (state != mLastState) { + int iconRes = getAnimationResForTransition(mLastState, state); + if (iconRes == -1) { + iconRes = getIconForState(state); + } + Drawable icon = mContext.getDrawable(iconRes); + AnimatedVectorDrawable animation = null; + if (icon instanceof AnimatedVectorDrawable) { + animation = (AnimatedVectorDrawable) icon; + } + int iconHeight = getResources().getDimensionPixelSize( + R.dimen.keyguard_affordance_icon_height); + int iconWidth = getResources().getDimensionPixelSize( + R.dimen.keyguard_affordance_icon_width); + if (!anyFingerprintIcon && (icon.getIntrinsicHeight() != iconHeight + || icon.getIntrinsicWidth() != iconWidth)) { + icon = new IntrinsicSizeDrawable(icon, iconWidth, iconHeight); + } + setPaddingRelative(0, 0, 0, anyFingerprintIcon + ? getResources().getDimensionPixelSize( + R.dimen.fingerprint_icon_additional_padding) + : 0); + setRestingAlpha( + anyFingerprintIcon ? 1f : KeyguardAffordanceHelper.SWIPE_RESTING_ALPHA_AMOUNT); + setImageDrawable(icon); + if (animation != null) { + animation.start(); + } + } + + // Hide trust circle when fingerprint is running. + boolean trustManaged = mUnlockMethodCache.isTrustManaged() && !anyFingerprintIcon; + mTrustDrawable.setTrustManaged(trustManaged); + mLastState = state; + updateClickability(); + } + + private void updateClickability() { + if (mAccessibilityController == null) { + return; + } + boolean clickToUnlock = mAccessibilityController.isTouchExplorationEnabled(); + boolean clickToForceLock = mUnlockMethodCache.isTrustManaged() + && !mAccessibilityController.isAccessibilityEnabled(); + boolean longClickToForceLock = mUnlockMethodCache.isTrustManaged() + && !clickToForceLock; + setClickable(clickToForceLock || clickToUnlock); + setLongClickable(longClickToForceLock); + setFocusable(mAccessibilityController.isAccessibilityEnabled()); + } + + public void setAccessibilityController(AccessibilityController accessibilityController) { + mAccessibilityController = accessibilityController; + } + + private int getIconForState(int state) { + switch (state) { + case STATE_LOCKED: + return R.drawable.ic_lock_24dp; + case STATE_LOCK_OPEN: + return R.drawable.ic_lock_open_24dp; + case STATE_FACE_UNLOCK: + return com.android.internal.R.drawable.ic_account_circle; + case STATE_FINGERPRINT: + return R.drawable.ic_fingerprint; + case STATE_FINGERPRINT_ERROR: + return R.drawable.ic_fingerprint_error; + default: + throw new IllegalArgumentException(); + } + } + + private int getAnimationResForTransition(int oldState, int newState) { + if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_ERROR) { + return R.drawable.lockscreen_fingerprint_error_state_animation; + } else { + return -1; + } + } + + private int getState() { + boolean fingerprintRunning = + KeyguardUpdateMonitor.getInstance(mContext).isFingerprintDetectionRunning(); + if (mTransientFpError) { + return STATE_FINGERPRINT_ERROR; + } else if (fingerprintRunning) { + return STATE_FINGERPRINT; + } else if (mUnlockMethodCache.isFaceUnlockRunning()) { + return STATE_FACE_UNLOCK; + } else if (mUnlockMethodCache.isCurrentlyInsecure()) { + return STATE_LOCK_OPEN; + } else { + return STATE_LOCKED; + } + } + + /** + * A wrapper around another Drawable that overrides the intrinsic size. + */ + private static class IntrinsicSizeDrawable extends InsetDrawable { + + private final int mIntrinsicWidth; + private final int mIntrinsicHeight; + + public IntrinsicSizeDrawable(Drawable drawable, int intrinsicWidth, int intrinsicHeight) { + super(drawable, 0); + mIntrinsicWidth = intrinsicWidth; + mIntrinsicHeight = intrinsicHeight; + } + + @Override + public int getIntrinsicWidth() { + return mIntrinsicWidth; + } + + @Override + public int getIntrinsicHeight() { + return mIntrinsicHeight; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index b87c25b43ba5..7b13e4b1bf6b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -182,11 +182,11 @@ public class NotificationPanelView extends PanelView implements private float mKeyguardStatusBarAnimateAlpha = 1f; private int mOldLayoutDirection; - private HeadsUpTouchHelper mHeadsUpTouchHelper = new HeadsUpTouchHelper(); - private boolean mPinnedHeadsUpExist; - private boolean mExpansionIsFromHeadsUp; - private int mBottomBarHeight; + private HeadsUpTouchHelper mHeadsUpTouchHelper; + private boolean mIsExpansionFromHeadsUp; + private int mNavigationBarBottomHeight; private boolean mExpandingFromHeadsUp; + private boolean mCollapsedOnDown; private int mPositionMinSideMargin; private int mLastOrientation = -1; @@ -327,7 +327,7 @@ public class NotificationPanelView extends PanelView implements } else if (!mQsExpanded) { setQsExpansion(mQsMinExpansionHeight + mLastOverscroll); } - mNotificationStackScroller.setStackHeight(getExpandedHeight()); + updateStackHeight(getExpandedHeight()); updateHeader(); mNotificationStackScroller.updateIsSmallScreen( mHeader.getCollapsedHeight() + mQsPeekHeight); @@ -534,17 +534,16 @@ public class NotificationPanelView extends PanelView implements } @Override - public boolean - onInterceptTouchEvent(MotionEvent event) { + public boolean onInterceptTouchEvent(MotionEvent event) { if (mBlockTouches) { return false; } initDownStates(event); if (mHeadsUpTouchHelper.onInterceptTouchEvent(event)) { - mExpansionIsFromHeadsUp = true; + mIsExpansionFromHeadsUp = true; return true; } - if (!isShadeCollapsed() && onQsIntercept(event)) { + if (!isFullyCollapsed() && onQsIntercept(event)) { return true; } return super.onInterceptTouchEvent(event); @@ -641,6 +640,7 @@ public class NotificationPanelView extends PanelView implements mOnlyAffordanceInThisMotion = false; mQsTouchAboveFalsingThreshold = mQsFullyExpanded; mDozingOnDown = isDozing(); + mCollapsedOnDown = isFullyCollapsed(); } } @@ -695,7 +695,7 @@ public class NotificationPanelView extends PanelView implements return true; } mHeadsUpTouchHelper.onTouchEvent(event); - if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && handleQSTouch(event)) { + if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && handleQsTouch(event)) { return true; } if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) { @@ -705,7 +705,7 @@ public class NotificationPanelView extends PanelView implements return true; } - private boolean handleQSTouch(MotionEvent event) { + private boolean handleQsTouch(MotionEvent event) { if (event.getActionMasked() == MotionEvent.ACTION_DOWN && getExpandedFraction() == 1f && mStatusBar.getBarState() != StatusBarState.KEYGUARD && !mQsExpanded && mQsExpansionEnabled) { @@ -718,7 +718,7 @@ public class NotificationPanelView extends PanelView implements mInitialTouchY = event.getX(); mInitialTouchX = event.getY(); } - if (!isShadeCollapsed()) { + if (!isFullyCollapsed()) { handleQsDown(event); } if (!mQsExpandImmediate && mQsTracking) { @@ -731,7 +731,7 @@ public class NotificationPanelView extends PanelView implements || event.getActionMasked() == MotionEvent.ACTION_UP) { mConflictingQsExpansionGesture = false; } - if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isShadeCollapsed() + if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed() && mQsExpansionEnabled) { mTwoFingerQsExpandPossible = true; } @@ -1191,8 +1191,8 @@ public class NotificationPanelView extends PanelView implements updateEmptyShadeView(); mQsNavbarScrim.setVisibility(mStatusBarState == StatusBarState.SHADE && mQsExpanded && !mStackScrollerOverscrolling && mQsScrimEnabled - ? View.VISIBLE - : View.INVISIBLE); + ? View.VISIBLE + : View.INVISIBLE); if (mKeyguardUserSwitcher != null && mQsExpanded && !mStackScrollerOverscrolling) { mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */); } @@ -1386,7 +1386,7 @@ public class NotificationPanelView extends PanelView implements * @return Whether we should intercept a gesture to open Quick Settings. */ private boolean shouldQuickSettingsIntercept(float x, float y, float yDiff) { - if (!mQsExpansionEnabled) { + if (!mQsExpansionEnabled || mCollapsedOnDown) { return false; } View header = mKeyguardShowing ? mKeyguardStatusBar : mHeader; @@ -1457,12 +1457,12 @@ public class NotificationPanelView extends PanelView implements setQsExpansion(mQsMinExpansionHeight + t * (getTempQsMaxExpansion() - mQsMinExpansionHeight)); } - mNotificationStackScroller.setStackHeight(expandedHeight); + updateStackHeight(expandedHeight); updateHeader(); updateUnlockIcon(); updateNotificationTranslucency(); - mHeadsUpManager.setIsExpanded(!isShadeCollapsed()); - mNotificationStackScroller.setShadeExpanded(!isShadeCollapsed()); + mHeadsUpManager.setIsExpanded(!isFullyCollapsed()); + mNotificationStackScroller.setShadeExpanded(!isFullyCollapsed()); if (DEBUG) { invalidate(); } @@ -1535,21 +1535,19 @@ public class NotificationPanelView extends PanelView implements float alpha; if (mExpandingFromHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()) { alpha = 1f; - if (mNotificationStackScroller.getLayerType() == LAYER_TYPE_HARDWARE) { - mNotificationStackScroller.setLayerType(LAYER_TYPE_NONE, null); - } } else { alpha = (getNotificationsTopY() + mNotificationStackScroller.getItemHeight()) / (mQsMinExpansionHeight + mNotificationStackScroller.getBottomStackPeekSize() - mNotificationStackScroller.getCollapseSecondCardPadding()); alpha = Math.max(0, Math.min(alpha, 1)); alpha = (float) Math.pow(alpha, 0.75); - if (alpha != 1f && mNotificationStackScroller.getLayerType() != LAYER_TYPE_HARDWARE) { - mNotificationStackScroller.setLayerType(LAYER_TYPE_HARDWARE, null); - } else if (alpha == 1f - && mNotificationStackScroller.getLayerType() == LAYER_TYPE_HARDWARE) { - mNotificationStackScroller.setLayerType(LAYER_TYPE_NONE, null); - } + } + + if (alpha != 1f && mNotificationStackScroller.getLayerType() != LAYER_TYPE_HARDWARE) { + mNotificationStackScroller.setLayerType(LAYER_TYPE_HARDWARE, null); + } else if (alpha == 1f + && mNotificationStackScroller.getLayerType() == LAYER_TYPE_HARDWARE) { + mNotificationStackScroller.setLayerType(LAYER_TYPE_NONE, null); } mNotificationStackScroller.setAlpha(alpha); } @@ -1615,7 +1613,7 @@ public class NotificationPanelView extends PanelView implements } float stackTranslation = mNotificationStackScroller.getStackTranslation(); float translation = stackTranslation / HEADER_RUBBERBAND_FACTOR; - if (mHeadsUpManager.hasPinnedHeadsUp() || mExpansionIsFromHeadsUp) { + if (mHeadsUpManager.hasPinnedHeadsUp() || mIsExpansionFromHeadsUp) { translation = mNotificationStackScroller.getTopPadding() + stackTranslation - mNotificationTopPadding - mQsMinExpansionHeight; } @@ -1683,16 +1681,16 @@ public class NotificationPanelView extends PanelView implements mHeadsUpManager.onExpandingFinished(); mIsExpanding = false; mScrollYOverride = -1; - if (isShadeCollapsed()) { + if (isFullyCollapsed()) { setListening(false); } else { setListening(true); } mQsExpandImmediate = false; mTwoFingerQsExpandPossible = false; - mExpansionIsFromHeadsUp = false; - mNotificationStackScroller.setTrackingHeadsUp(mHeadsUpTouchHelper.isTrackingHeadsUp()); - mExpandingFromHeadsUp = mHeadsUpTouchHelper.isTrackingHeadsUp(); + mIsExpansionFromHeadsUp = false; + mNotificationStackScroller.setTrackingHeadsUp(false); + mExpandingFromHeadsUp = false; } private void setListening(boolean listening) { @@ -1793,13 +1791,13 @@ public class NotificationPanelView extends PanelView implements @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { - mBottomBarHeight = insets.getSystemWindowInsetBottom(); + mNavigationBarBottomHeight = insets.getSystemWindowInsetBottom(); updateMaxHeadsUpTranslation(); return insets; } private void updateMaxHeadsUpTranslation() { - mNotificationStackScroller.setHeadsUpBoundaries(getHeight(), mBottomBarHeight); + mNotificationStackScroller.setHeadsUpBoundaries(getHeight(), mNavigationBarBottomHeight); } @Override @@ -2160,48 +2158,43 @@ public class NotificationPanelView extends PanelView implements } @Override - public void OnPinnedHeadsUpExistChanged(final boolean exist, boolean changeImmediatly) { - if (exist != mPinnedHeadsUpExist) { - mPinnedHeadsUpExist = exist; - if (exist) { - mHeadsUpExistenceChangedRunnable.run(); - updateNotificationTranslucency(); - } else { - mNotificationStackScroller.performOnAnimationFinished( - mHeadsUpExistenceChangedRunnable); - } + public void onPinnedModeChanged(final boolean inPinnedMode) { + if (inPinnedMode) { + mHeadsUpExistenceChangedRunnable.run(); + updateNotificationTranslucency(); + } else { + mNotificationStackScroller.runAfterAnimationFinished( + mHeadsUpExistenceChangedRunnable); } } @Override - public void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp) { - if (isHeadsUp) { - mNotificationStackScroller.generateHeadsUpAnimation(headsUp, true); - } + public void onHeadsUpPinned(ExpandableNotificationRow headsUp) { + mNotificationStackScroller.generateHeadsUpAnimation(headsUp, true); } @Override - public void OnHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) { - mNotificationStackScroller.generateHeadsUpAnimation(entry.row, isHeadsUp); + public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) { } @Override - protected boolean isShadeCollapsed() { - return mExpandedHeight == 0; + public void onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) { + mNotificationStackScroller.generateHeadsUpAnimation(entry.row, isHeadsUp); } @Override public void setHeadsUpManager(HeadsUpManager headsUpManager) { super.setHeadsUpManager(headsUpManager); - mHeadsUpTouchHelper.bind(headsUpManager, mNotificationStackScroller, this); + mHeadsUpTouchHelper = new HeadsUpTouchHelper(headsUpManager, mNotificationStackScroller, + this); } public void setTrackingHeadsUp(boolean tracking) { if (tracking) { - // otherwise we update the state when the expansion is finished mNotificationStackScroller.setTrackingHeadsUp(true); mExpandingFromHeadsUp = true; } + // otherwise we update the state when the expansion is finished } @Override @@ -2241,4 +2234,9 @@ public class NotificationPanelView extends PanelView implements mScrollView.setTranslationX(translation); mHeader.setTranslationX(translation); } + + private void updateStackHeight(float stackHeight) { + mNotificationStackScroller.setStackHeight(stackHeight); + updateKeyguardBottomAreaAlpha(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index 4452dd7cab5d..85f312c0da2d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -46,13 +46,13 @@ import java.io.PrintWriter; public abstract class PanelView extends FrameLayout { public static final boolean DEBUG = PanelBar.DEBUG; public static final String TAG = PanelView.class.getSimpleName(); - protected HeadsUpManager mHeadsUpManager; - private final void logf(String fmt, Object... args) { Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args)); } protected PhoneStatusBar mStatusBar; + protected HeadsUpManager mHeadsUpManager; + private float mPeekHeight; private float mHintDistance; private int mEdgeTapAreaWidth; @@ -242,15 +242,15 @@ public abstract class PanelView extends FrameLayout { final float y = event.getY(pointerIndex); if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { - mGestureWaitForTouchSlop = isShadeCollapsed() || hasConflictingGestures(); - mIgnoreXTouchSlop = isShadeCollapsed() || shouldGestureIgnoreXTouchSlop(x, y); + mGestureWaitForTouchSlop = isFullyCollapsed() || hasConflictingGestures(); + mIgnoreXTouchSlop = isFullyCollapsed() || shouldGestureIgnoreXTouchSlop(x, y); } switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: startExpandMotion(x, y, false /* startTracking */, mExpandedHeight); mJustPeeked = false; - mPanelClosedOnDown = isShadeCollapsed(); + mPanelClosedOnDown = isFullyCollapsed(); mHasLayoutedSinceDown = false; mUpdateFlingOnLayout = false; mMotionAborted = false; @@ -268,7 +268,7 @@ public abstract class PanelView extends FrameLayout { || mPeekPending || mPeekAnimator != null; onTrackingStarted(); } - if (isShadeCollapsed()) { + if (isFullyCollapsed()) { schedulePeek(); } break; @@ -472,7 +472,7 @@ public abstract class PanelView extends FrameLayout { mTouchSlopExceeded = false; mJustPeeked = false; mMotionAborted = false; - mPanelClosedOnDown = isShadeCollapsed(); + mPanelClosedOnDown = isFullyCollapsed(); mHasLayoutedSinceDown = false; mUpdateFlingOnLayout = false; mTouchAboveFalsingThreshold = false; @@ -707,7 +707,7 @@ public abstract class PanelView extends FrameLayout { // If the user isn't actively poking us, let's update the height if ((!mTracking || isTrackingBlocked()) && mHeightAnimator == null - && !isShadeCollapsed() + && !isFullyCollapsed() && currentMaxPanelHeight != mExpandedHeight && !mPeekPending && mPeekAnimator == null @@ -1057,8 +1057,6 @@ public abstract class PanelView extends FrameLayout { */ protected abstract int getClearAllHeight(); - protected abstract boolean isShadeCollapsed(); - public void setHeadsUpManager(HeadsUpManager headsUpManager) { mHeadsUpManager = headsUpManager; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index bf85ed5a4e19..bf27e843eda8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -1152,11 +1152,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, @Override public void removeNotification(String key, RankingMap ranking) { - boolean defferRemoval = false; + boolean deferRemoval = false; if (mHeadsUpManager.isHeadsUp(key)) { - defferRemoval = !mHeadsUpManager.removeNotification(key); + deferRemoval = !mHeadsUpManager.removeNotification(key); } - if (defferRemoval) { + if (deferRemoval) { mLatestRankingMap = ranking; mHeadsUpEntriesToRemoveOnSwitch.add(mHeadsUpManager.getEntry(key)); return; @@ -1293,13 +1293,20 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, updateClearAll(); updateEmptyShadeView(); - // Disable QS if device not provisioned. - // If the user switcher is simple then disable QS during setup because - // the user intends to use the lock screen user switcher, QS in not needed. + updateQsExpansionEnabled(); + mShadeUpdates.check(); + } + + /** + * Disable QS if device not provisioned. + * If the user switcher is simple then disable QS during setup because + * the user intends to use the lock screen user switcher, QS in not needed. + */ + private void updateQsExpansionEnabled() { mNotificationPanel.setQsExpansionEnabled(isDeviceProvisioned() && (mUserSetup || mUserSwitcherController == null - || !mUserSwitcherController.isSimpleUserSwitcher())); - mShadeUpdates.check(); + || !mUserSwitcherController.isSimpleUserSwitcher()) + && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0)); } private void updateNotificationShadeForChildren() { @@ -1732,6 +1739,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, flagdbg.append(((diff1 & StatusBarManager.DISABLE_CLOCK) != 0) ? "* " : " "); flagdbg.append(((state1 & StatusBarManager.DISABLE_SEARCH) != 0) ? "SEARCH" : "search"); flagdbg.append(((diff1 & StatusBarManager.DISABLE_SEARCH) != 0) ? "* " : " "); + flagdbg.append(((state2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) ? "QUICK_SETTINGS" + : "quick_settings"); + flagdbg.append(((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) ? "* " : " "); flagdbg.append(">"); Log.d(TAG, flagdbg.toString()); @@ -1780,6 +1790,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, (state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0; mHeadsUpObserver.onChange(true); } + + if ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) { + updateQsExpansionEnabled(); + } } @Override @@ -1838,8 +1852,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } @Override - public void OnPinnedHeadsUpExistChanged(boolean exist, boolean changeImmediatly) { - if (exist) { + public void onPinnedModeChanged(boolean inPinnedMode) { + if (inPinnedMode) { mStatusBarWindowManager.setHeadsUpShowing(true); } else { Runnable endRunnable = new Runnable() { @@ -1850,20 +1864,24 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } }; - if (changeImmediatly) { + if (!mNotificationPanel.isFullyCollapsed()) { endRunnable.run(); } else { - mStackScroller.performOnAnimationFinished(endRunnable); + mStackScroller.runAfterAnimationFinished(endRunnable); } } } @Override - public void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp) { + public void onHeadsUpPinned(ExpandableNotificationRow headsUp) { + } + + @Override + public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) { } @Override - public void OnHeadsUpStateChanged(Entry entry, boolean isHeadsUp) { + public void onHeadsUpStateChanged(Entry entry, boolean isHeadsUp) { if (!isHeadsUp && mHeadsUpEntriesToRemoveOnSwitch.contains(entry)) { removeNotification(entry.key, mLatestRankingMap); mHeadsUpEntriesToRemoveOnSwitch.remove(entry); @@ -1880,10 +1898,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, boolean alertAgain) { final boolean wasHeadsUp = isHeadsUp(key); if (wasHeadsUp) { - mHeadsUpManager.updateNotification(entry, alertAgain); if (!shouldInterrupt) { // We don't want this to be interrupting anymore, lets remove it mHeadsUpManager.removeNotification(key); + } else { + mHeadsUpManager.updateNotification(entry, alertAgain); } } else if (shouldInterrupt && alertAgain) { // This notification was updated to be a heads-up, show it! @@ -1929,7 +1948,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } @Override - public void escalateHeadsUp() { + public void maybeEscalateHeadsUp() { TreeSet<HeadsUpManager.HeadsUpEntry> entries = mHeadsUpManager.getSortedEntries(); for (HeadsUpManager.HeadsUpEntry entry : entries) { final StatusBarNotification sbn = entry.entry.notification; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index fb42ba1d975f..0e8e84439370 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -224,14 +224,14 @@ public class PhoneStatusBarPolicy { } else if (mZen == Global.ZEN_MODE_NO_INTERRUPTIONS) { zenVisible = true; zenIconId = R.drawable.stat_sys_zen_none; - zenDescription = mContext.getString(R.string.zen_no_interruptions); + zenDescription = mContext.getString(R.string.interruption_level_none); } else if (mZen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { zenVisible = true; zenIconId = R.drawable.stat_sys_zen_important; - zenDescription = mContext.getString(R.string.zen_important_interruptions); + zenDescription = mContext.getString(R.string.interruption_level_priority); } - if (DndTile.isVisible(mContext) + if (DndTile.isVisible(mContext) && !DndTile.isCombinedIcon(mContext) && audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) { volumeVisible = true; volumeIconId = R.drawable.stat_sys_ringer_silent; 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 e70178350e71..ae98e7654e87 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -80,7 +80,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, private float mCurrentInFrontAlpha; private float mCurrentBehindAlpha; private float mCurrentHeadsUpAlpha = 1; - private int mAmountOfPinnedHeadsUps; + private int mPinnedHeadsUpCount; private float mTopHeadsUpDragAmount; private View mDraggedHeadsUpView; @@ -347,25 +347,27 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, } @Override - public void OnPinnedHeadsUpExistChanged(boolean exist, boolean changeImmediatly) { + public void onPinnedModeChanged(boolean inPinnedMode) { } @Override - public void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp) { - if (isHeadsUp) { - mAmountOfPinnedHeadsUps++; - } else { - mAmountOfPinnedHeadsUps--; - if (headsUp == mDraggedHeadsUpView) { - mDraggedHeadsUpView = null; - mTopHeadsUpDragAmount = 0.0f; - } + public void onHeadsUpPinned(ExpandableNotificationRow headsUp) { + mPinnedHeadsUpCount++; + updateHeadsUpScrim(true); + } + + @Override + public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) { + mPinnedHeadsUpCount--; + if (headsUp == mDraggedHeadsUpView) { + mDraggedHeadsUpView = null; + mTopHeadsUpDragAmount = 0.0f; } updateHeadsUpScrim(true); } @Override - public void OnHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) { + public void onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) { } private void updateHeadsUpScrim(boolean animate) { @@ -374,12 +376,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, TAG_KEY_ANIM); float animEndValue = -1; if (previousAnimator != null) { - if ((animate || alpha == mCurrentHeadsUpAlpha)) { - // lets cancel any running animators + if (animate || alpha == mCurrentHeadsUpAlpha) { previousAnimator.cancel(); } - animEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim, - TAG_HUN_START_ALPHA); + animEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim, TAG_HUN_START_ALPHA); } if (alpha != mCurrentHeadsUpAlpha && alpha != animEndValue) { if (animate) { @@ -390,7 +390,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, if (previousAnimator != null) { float previousStartValue = StackStateAnimator.getChildTag(mHeadsUpScrim, TAG_HUN_START_ALPHA); - float previousEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim, + float previousEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim, TAG_HUN_END_ALPHA); // we need to increase all animation keyframes of the previous animator by the // relative change to the end value @@ -410,6 +410,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, } } + /** + * Set the amount the current top heads up view is dragged. The range is from 0 to 1 and 0 means + * the heads up is in its resting space and 1 means it's fully dragged out. + * + * @param draggedHeadsUpView the dragged view + * @param topHeadsUpDragAmount how far is it dragged + */ public void setTopHeadsUpDragAmount(View draggedHeadsUpView, float topHeadsUpDragAmount) { mTopHeadsUpDragAmount = topHeadsUpDragAmount; mDraggedHeadsUpView = draggedHeadsUpView; @@ -417,9 +424,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, } private float calculateHeadsUpAlpha() { - if (mAmountOfPinnedHeadsUps >= 2) { + if (mPinnedHeadsUpCount >= 2) { return 1.0f; - } else if (mAmountOfPinnedHeadsUps == 0) { + } else if (mPinnedHeadsUpCount == 0) { return 0.0f; } else { return 1.0f - mTopHeadsUpDragAmount; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java index b4e47731f61e..8f83daae4ba4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 The Android Open Source Project + * Copyright (C) 2015 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. @@ -35,11 +35,16 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Stack; import java.util.TreeSet; +/** + * A manager which handles heads up notifications which is a special mode where + * they simply peek from the top of the screen. + */ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsListener { private static final String TAG = "HeadsUpManager"; private static final boolean DEBUG = false; @@ -48,7 +53,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL private final int mHeadsUpNotificationDecay; private final int mMinimumDisplayTime; - private final int mTouchSensitivityDelay; + private final int mTouchAcceptanceDelay; private final ArrayMap<String, Long> mSnoozedPackages; private final HashSet<OnHeadsUpChangedListener> mListeners = new HashSet<>(); private final int mDefaultSnoozeLengthMs; @@ -67,13 +72,12 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL @Override public boolean release(HeadsUpEntry instance) { - instance.removeAutoCancelCallbacks(); + instance.reset(); mPoolObjects.push(instance); return true; } }; - private PhoneStatusBar mBar; private int mSnoozeLengthMs; private ContentObserver mSettingsObserver; @@ -86,13 +90,12 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL private boolean mTrackingHeadsUp; private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>(); private boolean mIsExpanded; - private boolean mHasPinnedHeadsUp; + private boolean mHasPinnedNotification; private int[] mTmpTwoArray = new int[2]; public HeadsUpManager(final Context context, ViewTreeObserver observer) { Resources resources = context.getResources(); - mTouchSensitivityDelay = resources.getInteger(R.integer.heads_up_sensitivity_delay); - if (DEBUG) Log.v(TAG, "create() " + mTouchSensitivityDelay); + mTouchAcceptanceDelay = resources.getInteger(R.integer.touch_acceptance_delay); mSnoozedPackages = new ArrayMap<>(); mDefaultSnoozeLengthMs = resources.getInteger(R.integer.heads_up_default_snooze_length_ms); mSnoozeLengthMs = mDefaultSnoozeLengthMs; @@ -116,7 +119,6 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL context.getContentResolver().registerContentObserver( Settings.Global.getUriFor(SETTING_HEADS_UP_SNOOZE_LENGTH_MS), false, mSettingsObserver); - if (DEBUG) Log.v(TAG, "mSnoozeLengthMs = " + mSnoozeLengthMs); observer.addOnComputeInternalInsetsListener(this); } @@ -154,7 +156,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL if (alert) { HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(headsUp.key); headsUpEntry.updateEntry(); - setEntryToShade(headsUpEntry, mIsExpanded, false /* justAdded */, false); + setEntryPinned(headsUpEntry, !mIsExpanded /* isPinned */); } } @@ -165,22 +167,23 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL headsUpEntry.setEntry(entry); mHeadsUpEntries.put(entry.key, headsUpEntry); entry.row.setHeadsUp(true); - setEntryToShade(headsUpEntry, mIsExpanded /* inShade */, true /* justAdded */, false); + setEntryPinned(headsUpEntry, !mIsExpanded /* isPinned */); for (OnHeadsUpChangedListener listener : mListeners) { - listener.OnHeadsUpStateChanged(entry, true); + listener.onHeadsUpStateChanged(entry, true); } entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); } - private void setEntryToShade(HeadsUpEntry headsUpEntry, boolean inShade, boolean justAdded, - boolean forceImmediate) { + private void setEntryPinned(HeadsUpEntry headsUpEntry, boolean isPinned) { ExpandableNotificationRow row = headsUpEntry.entry.row; - if (row.isInShade() != inShade || justAdded) { - row.setInShade(inShade); - if (!justAdded || !inShade) { - updatePinnedHeadsUpState(forceImmediate); - for (OnHeadsUpChangedListener listener : mListeners) { - listener.OnHeadsUpPinnedChanged(row, !inShade); + if (row.isPinned() != isPinned) { + row.setPinned(isPinned); + updatePinnedMode(); + for (OnHeadsUpChangedListener listener : mListeners) { + if (isPinned) { + listener.onHeadsUpPinned(row); + } else { + listener.onHeadsUpUnPinned(row); } } } @@ -189,24 +192,23 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL private void removeHeadsUpEntry(NotificationData.Entry entry) { HeadsUpEntry remove = mHeadsUpEntries.remove(entry.key); mSortedEntries.remove(remove); - mEntryPool.release(remove); entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); entry.row.setHeadsUp(false); - setEntryToShade(remove, true /* inShade */, false /* justAdded */, - false /* forceImmediate */); + setEntryPinned(remove, false /* isPinned */); for (OnHeadsUpChangedListener listener : mListeners) { - listener.OnHeadsUpStateChanged(entry, false); + listener.onHeadsUpStateChanged(entry, false); } + mEntryPool.release(remove); } - private void updatePinnedHeadsUpState(boolean forceImmediate) { - boolean hasPinnedHeadsUp = hasPinnedHeadsUpInternal(); - if (hasPinnedHeadsUp == mHasPinnedHeadsUp) { + private void updatePinnedMode() { + boolean hasPinnedNotification = hasPinnedNotificationInternal(); + if (hasPinnedNotification == mHasPinnedNotification) { return; } - mHasPinnedHeadsUp = hasPinnedHeadsUp; - for (OnHeadsUpChangedListener listener :mListeners) { - listener.OnPinnedHeadsUpExistChanged(hasPinnedHeadsUp, forceImmediate); + mHasPinnedNotification = hasPinnedNotification; + for (OnHeadsUpChangedListener listener : mListeners) { + listener.onPinnedModeChanged(hasPinnedNotification); } } @@ -222,7 +224,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL releaseImmediately(key); return true; } else { - getHeadsUpEntry(key).hideAsSoonAsPossible(); + getHeadsUpEntry(key).removeAsSoonAsPossible(); return false; } } @@ -245,14 +247,13 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL return mHeadsUpEntries.containsKey(key); } - /** * Push any current Heads Up notification down into the shade. */ public void releaseAllImmediately() { if (DEBUG) Log.v(TAG, "releaseAllImmediately"); - HashSet<String> keys = new HashSet<>(mHeadsUpEntries.keySet()); - for (String key: keys) { + ArrayList<String> keys = new ArrayList<>(mHeadsUpEntries.keySet()); + for (String key : keys) { releaseImmediately(key); } } @@ -280,7 +281,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL } public void snooze() { - for (String key: mHeadsUpEntries.keySet()) { + for (String key : mHeadsUpEntries.keySet()) { HeadsUpEntry entry = mHeadsUpEntries.get(key); String packageName = entry.entry.notification.getPackageName(); mSnoozedPackages.put(snoozeKey(packageName, mUser), @@ -310,8 +311,11 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL } /** + * Decides whether a click is invalid for a notification, i.e it has not been shown long enough + * that a user might have consciously clicked on it. + * * @param key the key of the touched notification - * @return whether the touch is valid and should not be discarded + * @return whether the touch is invalid and should be discarded */ public boolean shouldSwallowClick(String key) { HeadsUpEntry entry = mHeadsUpEntries.get(key); @@ -322,14 +326,14 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL } public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) { - if (!mIsExpanded && mHasPinnedHeadsUp) { + if (!mIsExpanded && mHasPinnedNotification) { int minX = Integer.MAX_VALUE; int maxX = 0; int minY = Integer.MAX_VALUE; int maxY = 0; - for (HeadsUpEntry entry: mSortedEntries) { + for (HeadsUpEntry entry : mSortedEntries) { ExpandableNotificationRow row = entry.entry.row; - if (!row.isInShade()) { + if (row.isPinned()) { row.getLocationOnScreen(mTmpTwoArray); minX = Math.min(minX, mTmpTwoArray[0]); minY = Math.min(minY, 0); @@ -349,7 +353,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("HeadsUpManager state:"); - pw.print(" mTouchSensitivityDelay="); pw.println(mTouchSensitivityDelay); + pw.print(" mTouchAcceptanceDelay="); pw.println(mTouchAcceptanceDelay); pw.print(" mSnoozeLengthMs="); pw.println(mSnoozeLengthMs); pw.print(" now="); pw.println(SystemClock.elapsedRealtime()); pw.print(" mUser="); pw.println(mUser); @@ -365,38 +369,32 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL } public boolean hasPinnedHeadsUp() { - return mHasPinnedHeadsUp; + return mHasPinnedNotification; } - private boolean hasPinnedHeadsUpInternal() { - for (String key: mHeadsUpEntries.keySet()) { + private boolean hasPinnedNotificationInternal() { + for (String key : mHeadsUpEntries.keySet()) { HeadsUpEntry entry = mHeadsUpEntries.get(key); - if (!entry.entry.row.isInShade()) { + if (entry.entry.row.isPinned()) { return true; } } return false; } - public void addSwipedOutKey(String key) { + /** + * Notifies that a notification was swiped out and will be removed. + * + * @param key the notification key + */ + public void addSwipedOutNotification(String key) { mSwipedOutKeys.add(key); } - public float getHighestPinnedHeadsUp() { - float max = 0; - for (HeadsUpEntry entry: mSortedEntries) { - if (!entry.entry.row.isInShade()) { - max = Math.max(max, entry.entry.row.getActualHeight()); - } - } - return max; - } - - public void releaseAllToShade() { - for (String key: mHeadsUpEntries.keySet()) { + public void unpinAll() { + for (String key : mHeadsUpEntries.keySet()) { HeadsUpEntry entry = mHeadsUpEntries.get(key); - setEntryToShade(entry, true /* toShade */, false /* justAdded */, - true /* forceImmediate */); + setEntryPinned(entry, false /* isPinned */); } } @@ -420,7 +418,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL if (isExpanded != mIsExpanded) { mIsExpanded = isExpanded; if (isExpanded) { - releaseAllToShade(); + unpinAll(); } } } @@ -430,6 +428,12 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL return topEntry != null ? topEntry.entry.row.getHeadsUpHeight() : 0; } + /** + * Compare two entries and decide how they should be ranked. + * + * @return -1 if the first argument should be ranked higher than the second, 1 if the second + * one should be ranked higher and 0 if they are equal. + */ public int compare(NotificationData.Entry a, NotificationData.Entry b) { HeadsUpEntry aEntry = getHeadsUpEntry(a.key); HeadsUpEntry bEntry = getHeadsUpEntry(b.key); @@ -439,6 +443,11 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL return aEntry.compareTo(bEntry); } + + /** + * This represents a notification and how long it is in a heads up mode. It also manages its + * lifecycle automatically when created. + */ public class HeadsUpEntry implements Comparable<HeadsUpEntry> { public NotificationData.Entry entry; public long postTime; @@ -449,7 +458,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL this.entry = entry; // The actual post time will be just after the heads-up really slided in - postTime = mClock.currentTimeMillis() + mTouchSensitivityDelay; + postTime = mClock.currentTimeMillis() + mTouchAcceptanceDelay; mRemoveHeadsUpRunnable = new Runnable() { @Override public void run() { @@ -467,7 +476,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL long currentTime = mClock.currentTimeMillis(); earliestRemovaltime = currentTime + mMinimumDisplayTime; postTime = Math.max(postTime, currentTime); - removeAutoCancelCallbacks(); + removeAutoRemovalCallbacks(); if (canEntryDecay()) { long finishTime = postTime + mHeadsUpNotificationDecay; long removeDelay = Math.max(finishTime - currentTime, mMinimumDisplayTime); @@ -487,7 +496,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL : -1; } - public void removeAutoCancelCallbacks() { + public void removeAutoRemovalCallbacks() { mHandler.removeCallbacks(mRemoveHeadsUpRunnable); } @@ -495,11 +504,17 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL return earliestRemovaltime < mClock.currentTimeMillis(); } - public void hideAsSoonAsPossible() { - removeAutoCancelCallbacks(); + public void removeAsSoonAsPossible() { + removeAutoRemovalCallbacks(); mHandler.postDelayed(mRemoveHeadsUpRunnable, earliestRemovaltime - mClock.currentTimeMillis()); } + + public void reset() { + removeAutoRemovalCallbacks(); + entry = null; + mRemoveHeadsUpRunnable = null; + } } /** @@ -519,8 +534,29 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL } public interface OnHeadsUpChangedListener { - void OnPinnedHeadsUpExistChanged(boolean exist, boolean changeImmediatly); - void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp); - void OnHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp); + /** + * The state whether there exist pinned heads-ups or not changed. + * + * @param inPinnedMode whether there are any pinned heads-ups + */ + void onPinnedModeChanged(boolean inPinnedMode); + + /** + * A notification was just pinned to the top. + */ + void onHeadsUpPinned(ExpandableNotificationRow headsUp); + + /** + * A notification was just unpinned from the top. + */ + void onHeadsUpUnPinned(ExpandableNotificationRow headsUp); + + /** + * A notification just became a heads up or turned back to its normal state. + * + * @param entry the entry of the changed notification + * @param isHeadsUp whether the notification is now a headsUp notification + */ + void onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java index 67cc788ca39f..9d84a85483cd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java @@ -35,6 +35,7 @@ public interface ZenModeController { boolean isZenAvailable(); ComponentName getEffectsSuppressor(); boolean isCountdownConditionSupported(); + int getCurrentUser(); public static class Callback { public void onZenChanged(int zen) {} @@ -45,4 +46,5 @@ public interface ZenModeController { public void onManualRuleChanged(ZenRule rule) {} public void onConfigChanged(ZenModeConfig config) {} } + }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java index 830a197bae2e..5b80ac28a6f6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.policy; +import android.app.ActivityManager; import android.app.AlarmManager; import android.app.NotificationManager; import android.content.BroadcastReceiver; @@ -159,6 +160,11 @@ public class ZenModeControllerImpl implements ZenModeController { .isSystemConditionProviderEnabled(ZenModeConfig.COUNTDOWN_PATH); } + @Override + public int getCurrentUser() { + return ActivityManager.getCurrentUser(); + } + private void fireNextAlarmChanged() { for (Callback cb : mCallbacks) { cb.onNextAlarmChanged(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/HeadsUpAppearInterpolator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/HeadsUpAppearInterpolator.java new file mode 100644 index 000000000000..05c0099359ab --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/HeadsUpAppearInterpolator.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2015 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.stack; + +import android.graphics.Path; +import android.view.animation.PathInterpolator; + +/** + * An interpolator specifically designed for the appear animation of heads up notifications. + */ +public class HeadsUpAppearInterpolator extends PathInterpolator { + public HeadsUpAppearInterpolator() { + super(getAppearPath()); + } + + private static Path getAppearPath() { + Path path = new Path(); + path.moveTo(0, 0); + float x1 = 250f; + float x2 = 150f; + float x3 = 100f; + float y1 = 90f; + float y2 = 78f; + float y3 = 80f; + float xTot = (x1 + x2 + x3); + path.cubicTo(x1 * 0.9f / xTot, 0f, + x1 * 0.8f / xTot, y1 / y3, + x1 / xTot , y1 / y3); + path.cubicTo((x1 + x2 * 0.4f) / xTot, y1 / y3, + (x1 + x2 * 0.2f) / xTot, y2 / y3, + (x1 + x2) / xTot, y2 / y3); + path.cubicTo((x1 + x2 + x3 * 0.4f) / xTot, y2 / y3, + (x1 + x2 + x3 * 0.2f) / xTot, 1f, + 1f, 1f); + return path; + } +} 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 88fc6020b69c..a1b0caef9dfc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -204,7 +204,6 @@ public class NotificationStackScrollLayout extends ViewGroup private ViewGroup mScrollView; private boolean mInterceptDelegateEnabled; private boolean mDelegateToScrollView; - private boolean mDisallowScrollingInThisMotion; private long mGoToFullShadeDelay; private ViewTreeObserver.OnPreDrawListener mChildrenUpdater @@ -487,9 +486,9 @@ public class NotificationStackScrollLayout extends ViewGroup int stackHeight; float paddingOffset; boolean trackingHeadsUp = mTrackingHeadsUp; - int normalExpandPositionStart = trackingHeadsUp ? mHeadsUpManager.getTopHeadsUpHeight() + int normalUnfoldPositionStart = trackingHeadsUp ? mHeadsUpManager.getTopHeadsUpHeight() : minStackHeight; - if (newStackHeight - mTopPadding - mTopPaddingOverflow >= normalExpandPositionStart + if (newStackHeight - mTopPadding - mTopPaddingOverflow >= normalUnfoldPositionStart || getNotGoneChildCount() == 0) { paddingOffset = mTopPaddingOverflow; stackHeight = newStackHeight; @@ -582,7 +581,7 @@ public class NotificationStackScrollLayout extends ViewGroup if (v instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) v; if (row.isHeadsUp()) { - mHeadsUpManager.addSwipedOutKey(row.getStatusBarNotification().getKey()); + mHeadsUpManager.addSwipedOutNotification(row.getStatusBarNotification().getKey()); } } final View veto = v.findViewById(R.id.veto); @@ -626,10 +625,10 @@ public class NotificationStackScrollLayout extends ViewGroup requestChildrenUpdate(); } - public boolean isPinnedHeadsUp(View v) { + public static boolean isPinnedHeadsUp(View v) { if (v instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) v; - return row.isHeadsUp() && !row.isInShade(); + return row.isHeadsUp() && row.isPinned(); } return false; } @@ -711,7 +710,7 @@ public class NotificationStackScrollLayout extends ViewGroup if (touchY >= top && touchY <= bottom && touchX >= left && touchX <= right) { if (slidingChild instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) slidingChild; - if (row.isHeadsUp() && !row.isInShade() + if (row.isHeadsUp() && row.isPinned() && mHeadsUpManager.getTopEntry().entry.row != row) { continue; } @@ -812,7 +811,8 @@ public class NotificationStackScrollLayout extends ViewGroup } handleEmptySpaceClick(ev); boolean expandWantsIt = false; - if (!mSwipingInProgress && !mOnlyScrollingInThisMotion && isScrollingEnabled()) { + if (mIsExpanded && !mSwipingInProgress && !mOnlyScrollingInThisMotion + && isScrollingEnabled()) { if (isCancelOrUp) { mExpandHelper.onlyObserveMovements(false); } @@ -824,7 +824,8 @@ public class NotificationStackScrollLayout extends ViewGroup } } boolean scrollerWantsIt = false; - if (!mSwipingInProgress && !mExpandingNotification && !mDisallowScrollingInThisMotion) { + if (mIsExpanded && !mSwipingInProgress && !mExpandingNotification + && !mDisallowScrollingInThisMotion) { scrollerWantsIt = onScrollTouch(ev); } boolean horizontalSwipeWantsIt = false; @@ -1872,15 +1873,15 @@ public class NotificationStackScrollLayout extends ViewGroup boolean onBottom = false; if (!mIsExpanded && !isHeadsUp) { type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR; - } else if (mAddedHeadsUpChildren.contains(row) || (!row.isInShade() && !mIsExpanded)) { - if (!row.isInShade() || shouldHunAppearFromBottom(row)) { + } else if (mAddedHeadsUpChildren.contains(row) || (row.isPinned() && !mIsExpanded)) { + if (row.isPinned() || shouldHunAppearFromBottom(row)) { // Our custom add animation type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_APPEAR; } else { // Normal add animation type = AnimationEvent.ANIMATION_TYPE_ADD; } - onBottom = row.isInShade(); + onBottom = !row.isPinned(); } AnimationEvent event = new AnimationEvent(row, type); event.headsUpFromBottom = onBottom; @@ -2670,7 +2671,7 @@ public class NotificationStackScrollLayout extends ViewGroup } } - public void performOnAnimationFinished(Runnable runnable) { + public void runAfterAnimationFinished(Runnable runnable) { mAnimationFinishedRunnables.add(runnable); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java index 2a49a4c583a2..202063ab9d65 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java @@ -311,7 +311,8 @@ public class StackScrollAlgorithm { StackViewState viewState = resultState.getViewStateForView( nextChild); // The child below the dragged one must be fully visible - if (!isPinnedHeadsUpView(draggedView) || isPinnedHeadsUpView(nextChild)) { + if (!NotificationStackScrollLayout.isPinnedHeadsUp(draggedView) + || NotificationStackScrollLayout.isPinnedHeadsUp(nextChild)) { viewState.alpha = 1; } } @@ -324,14 +325,6 @@ public class StackScrollAlgorithm { } } - private boolean isPinnedHeadsUpView(View view) { - if (view instanceof ExpandableNotificationRow) { - ExpandableNotificationRow row = (ExpandableNotificationRow) view; - return row.isHeadsUp() && !row.isInShade(); - } - return false; - } - /** * Update the visible children on the state. */ @@ -380,7 +373,7 @@ public class StackScrollAlgorithm { /** * Determine the positions for the views. This is the main part of the algorithm. * - * @param resultState The result state to update if a change to the properties of a child occurs + * @param resultState The result state to update if a change to the properties of a child occurs * @param algorithmState The state in which the current pass of the algorithm is currently in * @param ambientState The current ambient state */ @@ -515,11 +508,12 @@ public class StackScrollAlgorithm { } StackViewState childState = resultState.getViewStateForView(row); boolean isTopEntry = topHeadsUpEntry == row; - if (!row.isInShade()) { + if (row.isPinned()) { childState.yTranslation = 0; childState.height = row.getHeadsUpHeight(); if (!isTopEntry) { - // Ensure that a headsUp is never below the topmost headsUp + // Ensure that a headsUp doesn't vertically extend further than the heads-up at + // the top most z-position StackViewState topState = resultState.getViewStateForView(topHeadsUpEntry); childState.height = row.getHeadsUpHeight(); childState.yTranslation = topState.yTranslation + topState.height 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 f5d94c887c82..b9466d4dd103 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java @@ -21,11 +21,9 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; -import android.graphics.Path; import android.view.View; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; -import android.view.animation.PathInterpolator; import com.android.systemui.R; import com.android.systemui.statusbar.ExpandableNotificationRow; @@ -78,6 +76,7 @@ public class StackStateAnimator { private final Interpolator mFastOutSlowInInterpolator; private final Interpolator mHeadsUpAppearInterpolator; private final int mGoToFullShadeAppearingTranslation; + private final StackViewState mTmpState = new StackViewState(); public NotificationStackScrollLayout mHostLayout; private ArrayList<NotificationStackScrollLayout.AnimationEvent> mNewEvents = new ArrayList<>(); @@ -95,7 +94,6 @@ public class StackStateAnimator { private ValueAnimator mTopOverScrollAnimator; private ValueAnimator mBottomOverScrollAnimator; private ExpandableNotificationRow mChildExpandingView; - private StackViewState mTmpState = new StackViewState(); private int mHeadsUpAppearHeightBottom; private boolean mShadeExpanded; @@ -106,25 +104,7 @@ public class StackStateAnimator { mGoToFullShadeAppearingTranslation = hostLayout.getContext().getResources().getDimensionPixelSize( R.dimen.go_to_full_shade_appearing_translation); - Path path = new Path(); - path.moveTo(0, 0); - float x1 = 250f; - float x2 = 150f; - float x3 = 100f; - float y1 = 90f; - float y2 = 78f; - float y3 = 80f; - float xTot = (x1 + x2 + x3); - path.cubicTo(x1 * 0.9f / xTot, 0f, - x1 * 0.8f / xTot, y1 / y3, - x1 / xTot , y1 / y3); - path.cubicTo((x1 + x2 * 0.4f) / xTot, y1 / y3, - (x1 + x2 * 0.2f) / xTot, y2 / y3, - (x1 + x2) / xTot, y2 / y3); - path.cubicTo((x1 + x2 + x3 * 0.4f) / xTot, y2 / y3, - (x1 + x2 + x3 * 0.2f) / xTot, 1f, - 1f, 1f); - mHeadsUpAppearInterpolator = new PathInterpolator(path); + mHeadsUpAppearInterpolator = new HeadsUpAppearInterpolator(); } public boolean isRunning() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java index dda40d37540e..a5684a4cc189 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java @@ -121,7 +121,7 @@ public class TvStatusBar extends BaseStatusBar { } @Override - public void escalateHeadsUp() { + public void maybeEscalateHeadsUp() { } @Override diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java index 240c210bd209..deed8957173d 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java +++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java @@ -24,11 +24,17 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.MoveCallback; +import android.os.Handler; import android.os.UserHandle; import android.os.storage.DiskInfo; import android.os.storage.StorageEventListener; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; +import android.os.storage.VolumeRecord; +import android.text.TextUtils; +import android.text.format.DateUtils; import android.util.Log; import com.android.internal.R; @@ -39,12 +45,14 @@ import java.util.List; public class StorageNotification extends SystemUI { private static final String TAG = "StorageNotification"; - private static final int NOTIF_ID = 0x53544f52; // STOR + private static final int PUBLIC_ID = 0x53505542; // SPUB + private static final int PRIVATE_ID = 0x53505256; // SPRV + private static final int DISK_ID = 0x5344534b; // SDSK + private static final int MOVE_ID = 0x534d4f56; // SMOV private static final String ACTION_SNOOZE_VOLUME = "com.android.systemui.action.SNOOZE_VOLUME"; // TODO: delay some notifications to avoid bumpy fast operations - // TODO: annoy user when private media is missing private NotificationManager mNotificationManager; private StorageManager mStorageManager; @@ -52,17 +60,29 @@ public class StorageNotification extends SystemUI { private final StorageEventListener mListener = new StorageEventListener() { @Override public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) { - onVolumeStateChangedInternal(vol, oldState, newState); + onVolumeStateChangedInternal(vol); } @Override - public void onVolumeMetadataChanged(VolumeInfo vol) { + public void onVolumeMetadataChanged(String fsUuid) { // Avoid kicking notifications when getting early metadata before // mounted. If already mounted, we're being kicked because of a // nickname or init'ed change. - if (vol.isMountedReadable()) { - onVolumeStateChangedInternal(vol, vol.getState(), vol.getState()); + final VolumeInfo vol = mStorageManager.findVolumeByUuid(fsUuid); + if (vol != null && vol.isMountedReadable()) { + onVolumeStateChangedInternal(vol); } + + final VolumeRecord rec = mStorageManager.findRecordByUuid(fsUuid); + if (rec == null) { + // Private volume was probably just forgotten + mNotificationManager.cancelAsUser(fsUuid, PRIVATE_ID, UserHandle.ALL); + } + } + + @Override + public void onDiskScanned(DiskInfo disk, int volumeCount) { + onDiskScannedInternal(disk, volumeCount); } }; @@ -70,8 +90,19 @@ public class StorageNotification extends SystemUI { @Override public void onReceive(Context context, Intent intent) { // TODO: kick this onto background thread - final String volId = intent.getStringExtra(VolumeInfo.EXTRA_VOLUME_ID); - mStorageManager.setVolumeSnoozed(volId, true); + final String fsUuid = intent.getStringExtra(VolumeRecord.EXTRA_FS_UUID); + mStorageManager.setVolumeSnoozed(fsUuid, true); + } + }; + + private final MoveCallback mMoveCallback = new MoveCallback() { + @Override + public void onStatusChanged(int moveId, String moveTitle, int status, long estMillis) { + if (PackageManager.isMoveStatusFinished(status)) { + onMoveFinished(moveId, moveTitle, status); + } else { + onMoveProgress(moveId, moveTitle, status, estMillis); + } } }; @@ -88,20 +119,99 @@ public class StorageNotification extends SystemUI { // Kick current state into place final List<VolumeInfo> vols = mStorageManager.getVolumes(); for (VolumeInfo vol : vols) { - onVolumeStateChangedInternal(vol, vol.getState(), vol.getState()); + onVolumeStateChangedInternal(vol); } + + mContext.getPackageManager().registerMoveCallback(mMoveCallback, new Handler()); + + updateMissingPrivateVolumes(); } - public void onVolumeStateChangedInternal(VolumeInfo vol, int oldState, int newState) { - // We only care about public volumes - if (vol.getType() != VolumeInfo.TYPE_PUBLIC) { - return; + private void updateMissingPrivateVolumes() { + final List<VolumeRecord> recs = mStorageManager.getVolumeRecords(); + for (VolumeRecord rec : recs) { + if (rec.getType() != VolumeInfo.TYPE_PRIVATE) continue; + + final String fsUuid = rec.getFsUuid(); + final VolumeInfo info = mStorageManager.findVolumeByUuid(fsUuid); + if (info != null && info.isMountedWritable()) { + // Yay, private volume is here! + mNotificationManager.cancelAsUser(fsUuid, PRIVATE_ID, UserHandle.ALL); + + } else { + // Boo, annoy the user to reinsert the private volume + final CharSequence title = mContext.getString(R.string.ext_media_missing_title, + rec.getNickname()); + final CharSequence text = mContext.getString(R.string.ext_media_missing_message); + + final Notification notif = new Notification.Builder(mContext) + .setSmallIcon(R.drawable.stat_notify_sdcard) + .setColor(mContext.getColor(R.color.system_notification_accent_color)) + .setContentTitle(title) + .setContentText(text) + .setStyle(new Notification.BigTextStyle().bigText(text)) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setLocalOnly(true) + .setContentIntent(buildForgetPendingIntent(rec)) + .setCategory(Notification.CATEGORY_SYSTEM) + .setOngoing(true) + .build(); + + mNotificationManager.notifyAsUser(fsUuid, PRIVATE_ID, notif, UserHandle.ALL); + } + } + } + + private void onDiskScannedInternal(DiskInfo disk, int volumeCount) { + if (volumeCount == 0) { + // No supported volumes found, give user option to format + final CharSequence title = mContext.getString( + R.string.ext_media_unmountable_notification_title, disk.getDescription()); + final CharSequence text = mContext.getString( + R.string.ext_media_unmountable_notification_message, disk.getDescription()); + + final Notification notif = new Notification.Builder(mContext) + .setSmallIcon(getSmallIcon(disk, VolumeInfo.STATE_UNMOUNTABLE)) + .setColor(mContext.getColor(R.color.system_notification_accent_color)) + .setContentTitle(title) + .setContentText(text) + .setStyle(new Notification.BigTextStyle().bigText(text)) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setLocalOnly(true) + .setContentIntent(buildInitPendingIntent(disk)) + .setCategory(Notification.CATEGORY_ERROR) + .build(); + + mNotificationManager.notifyAsUser(disk.getId(), DISK_ID, notif, UserHandle.ALL); + + } else { + // Yay, we have volumes! + mNotificationManager.cancelAsUser(disk.getId(), DISK_ID, UserHandle.ALL); } + } - Log.d(TAG, vol.toString()); + private void onVolumeStateChangedInternal(VolumeInfo vol) { + switch (vol.getType()) { + case VolumeInfo.TYPE_PRIVATE: + onPrivateVolumeStateChangedInternal(vol); + break; + case VolumeInfo.TYPE_PUBLIC: + onPublicVolumeStateChangedInternal(vol); + break; + } + } + + private void onPrivateVolumeStateChangedInternal(VolumeInfo vol) { + Log.d(TAG, "Notifying about private volume: " + vol.toString()); + + updateMissingPrivateVolumes(); + } + + private void onPublicVolumeStateChangedInternal(VolumeInfo vol) { + Log.d(TAG, "Notifying about public volume: " + vol.toString()); final Notification notif; - switch (newState) { + switch (vol.getState()) { case VolumeInfo.STATE_UNMOUNTED: notif = onVolumeUnmounted(vol); break; @@ -133,9 +243,9 @@ public class StorageNotification extends SystemUI { } if (notif != null) { - mNotificationManager.notifyAsUser(vol.getId(), NOTIF_ID, notif, UserHandle.ALL); + mNotificationManager.notifyAsUser(vol.getId(), PUBLIC_ID, notif, UserHandle.ALL); } else { - mNotificationManager.cancelAsUser(vol.getId(), NOTIF_ID, UserHandle.ALL); + mNotificationManager.cancelAsUser(vol.getId(), PUBLIC_ID, UserHandle.ALL); } } @@ -159,20 +269,24 @@ public class StorageNotification extends SystemUI { } private Notification onVolumeMounted(VolumeInfo vol) { + final VolumeRecord rec = mStorageManager.findRecordByUuid(vol.getFsUuid()); + // Don't annoy when user dismissed in past - if (vol.isSnoozed()) return null; + if (rec.isSnoozed()) return null; final DiskInfo disk = vol.getDisk(); - if (disk.isAdoptable() && !vol.isInited()) { + if (disk.isAdoptable() && !rec.isInited()) { final CharSequence title = disk.getDescription(); final CharSequence text = mContext.getString( R.string.ext_media_new_notification_message, disk.getDescription()); + final PendingIntent initAction = buildInitPendingIntent(vol); return buildNotificationBuilder(vol, title, text) .addAction(new Action(0, mContext.getString(R.string.ext_media_init_action), - buildInitPendingIntent(vol))) + initAction)) .addAction(new Action(0, mContext.getString(R.string.ext_media_unmount_action), buildUnmountPendingIntent(vol))) + .setContentIntent(initAction) .setDeleteIntent(buildSnoozeIntent(vol)) .setCategory(Notification.CATEGORY_SYSTEM) .build(); @@ -182,11 +296,13 @@ public class StorageNotification extends SystemUI { final CharSequence text = mContext.getString( R.string.ext_media_ready_notification_message, disk.getDescription()); + final PendingIntent browseAction = buildBrowsePendingIntent(vol); return buildNotificationBuilder(vol, title, text) .addAction(new Action(0, mContext.getString(R.string.ext_media_browse_action), - buildBrowsePendingIntent(vol))) + browseAction)) .addAction(new Action(0, mContext.getString(R.string.ext_media_unmount_action), buildUnmountPendingIntent(vol))) + .setContentIntent(browseAction) .setDeleteIntent(buildSnoozeIntent(vol)) .setCategory(Notification.CATEGORY_SYSTEM) .setPriority(Notification.PRIORITY_LOW) @@ -260,16 +376,84 @@ public class StorageNotification extends SystemUI { .build(); } - private int getSmallIcon(VolumeInfo vol) { - if (vol.disk.isSd()) { - switch (vol.getState()) { + private void onMoveProgress(int moveId, String moveTitle, int status, long estMillis) { + final CharSequence title; + if (!TextUtils.isEmpty(moveTitle)) { + title = mContext.getString(R.string.ext_media_move_specific_title, moveTitle); + } else { + title = mContext.getString(R.string.ext_media_move_title); + } + + final CharSequence text; + if (estMillis < 0) { + text = null; + } else { + text = DateUtils.formatDuration(estMillis); + } + + final Notification notif = new Notification.Builder(mContext) + .setSmallIcon(R.drawable.stat_notify_sdcard) + .setColor(mContext.getColor(R.color.system_notification_accent_color)) + .setContentTitle(title) + .setContentText(text) + .setStyle(new Notification.BigTextStyle().bigText(text)) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setLocalOnly(true) + .setCategory(Notification.CATEGORY_PROGRESS) + .setPriority(Notification.PRIORITY_LOW) + .setProgress(100, status, false) + .setOngoing(true) + .build(); + + mNotificationManager.notifyAsUser(moveTitle, MOVE_ID, notif, UserHandle.ALL); + } + + private void onMoveFinished(int moveId, String moveTitle, int status) { + if (!TextUtils.isEmpty(moveTitle)) { + // We currently ignore finished app moves; just clear the last + // published progress + mNotificationManager.cancelAsUser(moveTitle, MOVE_ID, UserHandle.ALL); + return; + } + + final VolumeInfo vol = mContext.getPackageManager().getPrimaryStorageCurrentVolume(); + final String descrip = mStorageManager.getBestVolumeDescription(vol); + + final CharSequence title; + final CharSequence text; + if (status == PackageManager.MOVE_SUCCEEDED) { + title = mContext.getString(R.string.ext_media_move_success_title); + text = mContext.getString(R.string.ext_media_move_success_message, descrip); + } else { + title = mContext.getString(R.string.ext_media_move_failure_title); + text = mContext.getString(R.string.ext_media_move_failure_message); + } + + final Notification notif = new Notification.Builder(mContext) + .setSmallIcon(R.drawable.stat_notify_sdcard) + .setColor(mContext.getColor(R.color.system_notification_accent_color)) + .setContentTitle(title) + .setContentText(text) + .setStyle(new Notification.BigTextStyle().bigText(text)) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setLocalOnly(true) + .setCategory(Notification.CATEGORY_SYSTEM) + .setPriority(Notification.PRIORITY_LOW) + .build(); + + mNotificationManager.notifyAsUser(moveTitle, MOVE_ID, notif, UserHandle.ALL); + } + + private int getSmallIcon(DiskInfo disk, int state) { + if (disk.isSd()) { + switch (state) { case VolumeInfo.STATE_CHECKING: case VolumeInfo.STATE_EJECTING: return R.drawable.stat_notify_sdcard_prepare; default: return R.drawable.stat_notify_sdcard; } - } else if (vol.disk.isUsb()) { + } else if (disk.isUsb()) { return R.drawable.stat_sys_data_usb; } else { return R.drawable.stat_notify_sdcard; @@ -279,7 +463,7 @@ public class StorageNotification extends SystemUI { private Notification.Builder buildNotificationBuilder(VolumeInfo vol, CharSequence title, CharSequence text) { return new Notification.Builder(mContext) - .setSmallIcon(getSmallIcon(vol)) + .setSmallIcon(getSmallIcon(vol.getDisk(), vol.getState())) .setColor(mContext.getColor(R.color.system_notification_accent_color)) .setContentTitle(title) .setContentText(text) @@ -288,6 +472,17 @@ public class StorageNotification extends SystemUI { .setLocalOnly(true); } + private PendingIntent buildInitPendingIntent(DiskInfo disk) { + final Intent intent = new Intent(); + intent.setClassName("com.android.settings", + "com.android.settings.deviceinfo.StorageWizardInit"); + intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.getId()); + + final int requestKey = disk.getId().hashCode(); + return PendingIntent.getActivityAsUser(mContext, requestKey, intent, + PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); + } + private PendingIntent buildInitPendingIntent(VolumeInfo vol) { final Intent intent = new Intent(); intent.setClassName("com.android.settings", @@ -321,7 +516,7 @@ public class StorageNotification extends SystemUI { private PendingIntent buildDetailsPendingIntent(VolumeInfo vol) { final Intent intent = new Intent(); intent.setClassName("com.android.settings", - "com.android.settings.Settings$StorageVolumeSettingsActivity"); + "com.android.settings.Settings$PublicVolumeSettingsActivity"); intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId()); final int requestKey = vol.getId().hashCode(); @@ -331,10 +526,21 @@ public class StorageNotification extends SystemUI { private PendingIntent buildSnoozeIntent(VolumeInfo vol) { final Intent intent = new Intent(ACTION_SNOOZE_VOLUME); - intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId()); + intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.getFsUuid()); final int requestKey = vol.getId().hashCode(); return PendingIntent.getBroadcastAsUser(mContext, requestKey, intent, PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.CURRENT); } + + private PendingIntent buildForgetPendingIntent(VolumeRecord rec) { + final Intent intent = new Intent(); + intent.setClassName("com.android.settings", + "com.android.settings.Settings$PrivateVolumeForgetActivity"); + intent.putExtra(VolumeRecord.EXTRA_FS_UUID, rec.getFsUuid()); + + final int requestKey = rec.getFsUuid().hashCode(); + return PendingIntent.getActivityAsUser(mContext, requestKey, intent, + PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); + } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java b/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java index 4f20ac7b75b0..f7cb9fec61cd 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java +++ b/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java @@ -17,6 +17,7 @@ package com.android.systemui.volume; import android.content.Context; +import android.graphics.Typeface; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -30,6 +31,8 @@ import java.util.Objects; public class SegmentedButtons extends LinearLayout { private static final int LABEL_RES_KEY = R.id.label; + private static final Typeface REGULAR = Typeface.create("sans-serif", Typeface.NORMAL); + private static final Typeface MEDIUM = Typeface.create("sans-serif-medium", Typeface.NORMAL); private final Context mContext; private final LayoutInflater mInflater; @@ -60,6 +63,7 @@ public class SegmentedButtons extends LinearLayout { final Object tag = c.getTag(); final boolean selected = Objects.equals(mSelectedValue, tag); c.setSelected(selected); + c.setTypeface(selected ? MEDIUM : REGULAR); } fireOnSelected(); } diff --git a/packages/SystemUI/src/com/android/systemui/volume/Util.java b/packages/SystemUI/src/com/android/systemui/volume/Util.java index 216a4dafaac8..421409156a38 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/Util.java +++ b/packages/SystemUI/src/com/android/systemui/volume/Util.java @@ -144,9 +144,14 @@ class Util { return HMMAA.format(new Date(millis)); } - public static void setText(TextView tv, CharSequence text) { - if (Objects.equals(tv.getText(), text)) return; + private static CharSequence emptyToNull(CharSequence str) { + return str == null || str.length() == 0 ? null : str; + } + + public static boolean setText(TextView tv, CharSequence text) { + if (Objects.equals(emptyToNull(tv.getText()), emptyToNull(text))) return false; tv.setText(text); + return true; } public static final void setVisOrGone(View v, boolean vis) { diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java index bb4aa61e8e4d..94340369d31f 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java @@ -37,7 +37,6 @@ import android.os.Looper; import android.os.Message; import android.os.SystemClock; import android.provider.Settings.Global; -import android.service.notification.ZenModeConfig; import android.util.DisplayMetrics; import android.util.Log; import android.util.SparseBooleanArray; @@ -52,7 +51,6 @@ import android.view.ViewGroup.MarginLayoutParams; import android.view.Window; import android.view.WindowManager; import android.view.animation.DecelerateInterpolator; -import android.widget.Button; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.SeekBar; @@ -90,16 +88,12 @@ public class VolumeDialog { private final ViewGroup mDialogView; private final ViewGroup mDialogContentView; private final ImageButton mExpandButton; - private final TextView mFootlineText; - private final Button mFootlineAction; private final View mSettingsButton; - private final View mFooter; private final List<VolumeRow> mRows = new ArrayList<VolumeRow>(); private final SpTexts mSpTexts; private final SparseBooleanArray mDynamic = new SparseBooleanArray(); private final KeyguardManager mKeyguard; private final int mExpandButtonAnimationDuration; - private final View mTextFooter; private final ZenFooter mZenFooter; private final LayoutTransition mLayoutTransition; private final Object mSafetyWarningLock = new Object(); @@ -108,8 +102,6 @@ public class VolumeDialog { private boolean mExpanded; private int mActiveStream; private boolean mShowHeaders = VolumePrefs.DEFAULT_SHOW_HEADERS; - private boolean mShowFooter = VolumePrefs.DEFAULT_SHOW_FOOTER; - private boolean mShowZenFooter = VolumePrefs.DEFAULT_ZEN_FOOTER; private boolean mAutomute = VolumePrefs.DEFAULT_ENABLE_AUTOMUTE; private boolean mSilentMode = VolumePrefs.DEFAULT_ENABLE_SILENT_MODE; private State mState; @@ -118,7 +110,7 @@ public class VolumeDialog { private SafetyWarningDialog mSafetyWarning; private Callback mCallback; - public VolumeDialog(Context context, VolumeDialogController controller, + public VolumeDialog(Context context, int windowType, VolumeDialogController controller, ZenModeController zenModeController, Callback callback) { mContext = context; mController = controller; @@ -141,7 +133,7 @@ public class VolumeDialog { mDialog.setCanceledOnTouchOutside(true); final Resources res = mContext.getResources(); final WindowManager.LayoutParams lp = window.getAttributes(); - lp.type = WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY; + lp.type = windowType; lp.format = PixelFormat.TRANSLUCENT; lp.setTitle(VolumeDialog.class.getSimpleName()); lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; @@ -176,17 +168,11 @@ public class VolumeDialog { addRow(AudioManager.STREAM_SYSTEM, R.drawable.ic_volume_system, R.drawable.ic_volume_system_mute, false); - mTextFooter = mDialog.findViewById(R.id.volume_text_footer); - mFootlineText = (TextView) mDialog.findViewById(R.id.volume_footline_text); - mSpTexts.add(mFootlineText); - mFootlineAction = (Button) mDialog.findViewById(R.id.volume_footline_action_button); - mSpTexts.add(mFootlineAction); - mFooter = mDialog.findViewById(R.id.volume_footer); mSettingsButton = mDialog.findViewById(R.id.volume_settings_button); mSettingsButton.setOnClickListener(mClickSettings); mExpandButtonAnimationDuration = res.getInteger(R.integer.volume_expand_animation_duration); mZenFooter = (ZenFooter) mDialog.findViewById(R.id.volume_zen_footer); - mZenFooter.init(zenModeController, mZenFooterCallback); + mZenFooter.init(zenModeController); controller.addCallback(mControllerCallbackH, mHandler); controller.getState(); @@ -217,18 +203,6 @@ public class VolumeDialog { mHandler.sendEmptyMessage(H.RECHECK_ALL); } - public void setShowFooter(boolean show) { - if (mShowFooter == show) return; - mShowFooter = show; - mHandler.sendEmptyMessage(H.RECHECK_ALL); - } - - public void setZenFooter(boolean zen) { - if (mShowZenFooter == zen) return; - mShowZenFooter = zen; - mHandler.sendEmptyMessage(H.RECHECK_ALL); - } - public void setAutomute(boolean automute) { if (mAutomute == automute) return; mAutomute = automute; @@ -315,7 +289,6 @@ public class VolumeDialog { writer.print(" mActiveStream: "); writer.println(mActiveStream); writer.print(" mDynamic: "); writer.println(mDynamic); writer.print(" mShowHeaders: "); writer.println(mShowHeaders); - writer.print(" mShowFooter: "); writer.println(mShowFooter); writer.print(" mAutomute: "); writer.println(mAutomute); writer.print(" mSilentMode: "); writer.println(mSilentMode); } @@ -444,7 +417,6 @@ public class VolumeDialog { } private int computeTimeoutH() { - if (mZenFooter != null && mZenFooter.isFooterExpanded()) return 10000; if (mSafetyWarning != null) return 5000; if (mExpanded || mExpanding) return 5000; if (mActiveStream == AudioManager.STREAM_MUSIC) return 1500; @@ -515,18 +487,9 @@ public class VolumeDialog { final VolumeRow activeRow = getActiveRow(); updateFooterH(); updateExpandButtonH(); - final boolean footerVisible = mFooter.getVisibility() == View.VISIBLE; if (!mShowing) { trimObsoleteH(); } - // first, find the last visible row - VolumeRow lastVisible = null; - for (VolumeRow row : mRows) { - final boolean isActive = row == activeRow; - if (isVisibleH(row, isActive)) { - lastVisible = row; - } - } // apply changes to all rows for (VolumeRow row : mRows) { final boolean isActive = row == activeRow; @@ -542,8 +505,7 @@ public class VolumeDialog { row.settingsButton.setImageResource(expandButtonRes); } } - Util.setVisOrInvis(row.settingsButton, - mExpanded && (!footerVisible && row == lastVisible)); + Util.setVisOrInvis(row.settingsButton, false); row.header.setAlpha(mExpanded && isActive ? 1 : 0.5f); } } @@ -585,51 +547,9 @@ public class VolumeDialog { updateFooterH(); } - private void updateTextFooterH() { - final boolean zen = mState.zenMode != Global.ZEN_MODE_OFF; - final boolean wasVisible = mFooter.getVisibility() == View.VISIBLE; - Util.setVisOrGone(mTextFooter, mExpanded && mShowFooter && (zen || mShowing && wasVisible)); - if (mTextFooter.getVisibility() == View.VISIBLE) { - String text = null; - String action = null; - if (mState.exitCondition != null) { - final long countdown = ZenModeConfig.tryParseCountdownConditionId(mState - .exitCondition.id); - if (countdown != 0) { - text = mContext.getString(R.string.volume_dnd_ends_at, - Util.getShortTime(countdown)); - action = mContext.getString(R.string.volume_end_now); - } - } - if (text == null) { - text = mContext.getString(R.string.volume_dnd_is_on); - } - if (action == null) { - action = mContext.getString(R.string.volume_turn_off); - } - Util.setText(mFootlineText, text); - Util.setText(mFootlineAction, action); - mFootlineAction.setOnClickListener(mTurnOffDnd); - } - Util.setVisOrGone(mFootlineText, zen); - Util.setVisOrGone(mFootlineAction, zen); - } - private void updateFooterH() { - if (!mShowFooter) { - Util.setVisOrGone(mFooter, false); - return; - } - if (mShowZenFooter) { - Util.setVisOrGone(mTextFooter, false); - final boolean ringActive = mActiveStream == AudioManager.STREAM_RING; - Util.setVisOrGone(mZenFooter, mZenFooter.isZen() && ringActive - || mShowing && (mExpanded || mZenFooter.getVisibility() == View.VISIBLE)); - mZenFooter.update(); - } else { - Util.setVisOrGone(mZenFooter, false); - updateTextFooterH(); - } + Util.setVisOrGone(mZenFooter, mState.zenMode != Global.ZEN_MODE_OFF); + mZenFooter.update(); } private void updateVolumeRowH(VolumeRow row) { @@ -642,12 +562,20 @@ public class VolumeDialog { } final boolean isRingStream = row.stream == AudioManager.STREAM_RING; final boolean isSystemStream = row.stream == AudioManager.STREAM_SYSTEM; + final boolean isAlarmStream = row.stream == AudioManager.STREAM_ALARM; + final boolean isMusicStream = row.stream == AudioManager.STREAM_MUSIC; final boolean isRingVibrate = isRingStream && mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE; - final boolean isNoned = (isRingStream || isSystemStream) - && mState.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS; - final boolean isLimited = isRingStream - && mState.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; + final boolean isRingSilent = isRingStream + && mState.ringerModeInternal == AudioManager.RINGER_MODE_SILENT; + final boolean isZenAlarms = mState.zenMode == Global.ZEN_MODE_ALARMS; + final boolean isZenNone = mState.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS; + final boolean isZenPriority = mState.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; + final boolean isRingZenNone = (isRingStream || isSystemStream) && isZenNone; + final boolean isRingLimited = isRingStream && isZenPriority; + final boolean zenMuted = isZenAlarms ? (isRingStream || isSystemStream) + : isZenNone ? (isRingStream || isSystemStream || isAlarmStream || isMusicStream) + : false; // update slider max final int max = ss.levelMax * 100; @@ -663,15 +591,15 @@ public class VolumeDialog { // update header text final String text; - if (isNoned) { + if (isRingZenNone) { text = mContext.getString(R.string.volume_stream_muted_dnd, ss.name); - } else if (isRingVibrate && isLimited) { + } else if (isRingVibrate && isRingLimited) { text = mContext.getString(R.string.volume_stream_vibrate_dnd, ss.name); } else if (isRingVibrate) { text = mContext.getString(R.string.volume_stream_vibrate, ss.name); } else if (ss.muted || mAutomute && ss.level == 0) { text = mContext.getString(R.string.volume_stream_muted, ss.name); - } else if (isLimited) { + } else if (isRingLimited) { text = mContext.getString(R.string.volume_stream_limited_dnd, ss.name); } else { text = ss.name; @@ -679,11 +607,12 @@ public class VolumeDialog { Util.setText(row.header, text); // update icon - final boolean iconEnabled = mAutomute || ss.muteSupported; + final boolean iconEnabled = (mAutomute || ss.muteSupported) && !zenMuted; row.icon.setEnabled(iconEnabled); row.icon.setAlpha(iconEnabled ? 1 : 0.5f); final int iconRes = isRingVibrate ? R.drawable.ic_volume_ringer_vibrate + : isRingSilent || zenMuted ? row.cachedIconRes : ss.routedToBluetooth ? (ss.muted ? R.drawable.ic_volume_media_bt_mute : R.drawable.ic_volume_media_bt) @@ -705,10 +634,11 @@ public class VolumeDialog { : Events.ICON_STATE_UNKNOWN; // update slider - updateVolumeRowSliderH(row); + updateVolumeRowSliderH(row, zenMuted); } - private void updateVolumeRowSliderH(VolumeRow row) { + private void updateVolumeRowSliderH(VolumeRow row, boolean zenMuted) { + row.slider.setEnabled(!zenMuted); if (row.tracking) { return; // don't update if user is sliding } @@ -887,46 +817,6 @@ public class VolumeDialog { } }; - private final View.OnClickListener mTurnOffDnd = new View.OnClickListener() { - @Override - public void onClick(View v) { - mSettingsButton.postDelayed(new Runnable() { - @Override - public void run() { - mController.setZenMode(Global.ZEN_MODE_OFF); - } - }, WAIT_FOR_RIPPLE); - } - }; - - private final ZenFooter.Callback mZenFooterCallback = new ZenFooter.Callback() { - @Override - public void onFooterExpanded() { - mHandler.sendEmptyMessage(H.RESCHEDULE_TIMEOUT); - } - - @Override - public void onSettingsClicked() { - dismiss(Events.DISMISS_REASON_SETTINGS_CLICKED); - if (mCallback != null) { - mCallback.onZenSettingsClicked(); - } - } - - @Override - public void onDoneClicked() { - dismiss(Events.DISMISS_REASON_DONE_CLICKED); - } - - @Override - public void onPrioritySettingsClicked() { - dismiss(Events.DISMISS_REASON_SETTINGS_CLICKED); - if (mCallback != null) { - mCallback.onZenPrioritySettingsClicked(); - } - } - }; - private final class H extends Handler { private static final int SHOW = 1; private static final int DISMISS = 2; diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java index 86abfcc348e3..1083f407b421 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java @@ -24,6 +24,7 @@ import android.media.VolumePolicy; import android.os.Bundle; import android.os.Handler; import android.provider.Settings; +import android.view.WindowManager; import com.android.systemui.SystemUI; import com.android.systemui.keyguard.KeyguardViewMediator; @@ -61,7 +62,8 @@ public class VolumeDialogComponent implements VolumeComponent { } }; mZenModeController = zen; - mDialog = new VolumeDialog(context, mController, zen, mVolumeDialogCallback); + mDialog = new VolumeDialog(context, WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY, + mController, zen, mVolumeDialogCallback); applyConfiguration(); } @@ -76,12 +78,10 @@ public class VolumeDialogComponent implements VolumeComponent { mDialog.setStreamImportant(AudioManager.STREAM_ALARM, true); mDialog.setStreamImportant(AudioManager.STREAM_SYSTEM, false); mDialog.setShowHeaders(false); - mDialog.setShowFooter(true); - mDialog.setZenFooter(true); mDialog.setAutomute(true); mDialog.setSilentMode(false); mController.setVolumePolicy(mVolumePolicy); - mController.showDndTile(false); + mController.showDndTile(true); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java index 012eb41b2d30..3a8081fd80d0 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java @@ -100,7 +100,7 @@ public class VolumeDialogController { private boolean mEnabled; private boolean mDestroyed; private VolumePolicy mVolumePolicy; - private boolean mShowDndTile = false; + private boolean mShowDndTile = true; public VolumeDialogController(Context context, ComponentName component) { mContext = context.getApplicationContext(); @@ -125,6 +125,10 @@ public class VolumeDialogController { return mAudio; } + public ZenModeConfig getZenModeConfig() { + return mNoMan.getZenModeConfig(); + } + public void dismiss() { mCallbacks.onDismissRequested(Events.DISMISS_REASON_VOLUME_CONTROLLER); } @@ -342,7 +346,7 @@ public class VolumeDialogController { updateRingerModeExternalW(mAudio.getRingerMode()); updateZenModeW(); updateEffectsSuppressorW(mNoMan.getEffectsSuppressor()); - updateExitConditionW(); + updateZenModeConfigW(); mCallbacks.onStateChanged(mState); } @@ -395,17 +399,10 @@ public class VolumeDialogController { return stream == AudioManager.STREAM_RING || stream == AudioManager.STREAM_NOTIFICATION; } - private Condition getExitCondition() { - final ZenModeConfig config = mNoMan.getZenModeConfig(); - return config == null ? null - : config.manualRule == null ? null - : config.manualRule.condition; - } - - private boolean updateExitConditionW() { - final Condition exitCondition = getExitCondition(); - if (Objects.equals(mState.exitCondition, exitCondition)) return false; - mState.exitCondition = exitCondition; + private boolean updateZenModeConfigW() { + final ZenModeConfig zenModeConfig = getZenModeConfig(); + if (Objects.equals(mState.zenModeConfig, zenModeConfig)) return false; + mState.zenModeConfig = zenModeConfig; return true; } @@ -750,7 +747,7 @@ public class VolumeDialogController { changed = updateZenModeW(); } if (ZEN_MODE_CONFIG_URI.equals(uri)) { - changed = updateExitConditionW(); + changed = updateZenModeConfigW(); } if (changed) { mCallbacks.onStateChanged(mState); @@ -943,7 +940,7 @@ public class VolumeDialogController { public int zenMode; public ComponentName effectsSuppressor; public String effectsSuppressorName; - public Condition exitCondition; + public ZenModeConfig zenModeConfig; public int activeStream = NO_ACTIVE_STREAM; public State copy() { @@ -956,7 +953,7 @@ public class VolumeDialogController { rt.zenMode = zenMode; if (effectsSuppressor != null) rt.effectsSuppressor = effectsSuppressor.clone(); rt.effectsSuppressorName = effectsSuppressorName; - if (exitCondition != null) rt.exitCondition = exitCondition.copy(); + if (zenModeConfig != null) rt.zenModeConfig = zenModeConfig.copy(); rt.activeStream = activeStream; return rt; } @@ -977,10 +974,15 @@ public class VolumeDialogController { sb.append(",zenMode:").append(zenMode); sb.append(",effectsSuppressor:").append(effectsSuppressor); sb.append(",effectsSuppressorName:").append(effectsSuppressorName); - sb.append(",exitCondition:").append(exitCondition); + sb.append(",zenModeConfig:").append(zenModeConfig); sb.append(",activeStream:").append(activeStream); return sb.append('}').toString(); } + + public Condition getManualExitCondition() { + return zenModeConfig != null && zenModeConfig.manualRule != null + ? zenModeConfig.manualRule.condition : null; + } } public interface Callbacks { diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java index 915e998542ca..04339eb8e802 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java @@ -32,8 +32,6 @@ public class VolumePrefs { public static final String PREF_SHOW_HEADERS = "pref_show_headers"; public static final String PREF_SHOW_FAKE_REMOTE_1 = "pref_show_fake_remote_1"; public static final String PREF_SHOW_FAKE_REMOTE_2 = "pref_show_fake_remote_2"; - public static final String PREF_SHOW_FOOTER = "pref_show_footer"; - public static final String PREF_ZEN_FOOTER = "pref_zen_footer"; public static final String PREF_ENABLE_AUTOMUTE = "pref_enable_automute"; public static final String PREF_ENABLE_SILENT_MODE = "pref_enable_silent_mode"; public static final String PREF_DEBUG_LOGGING = "pref_debug_logging"; @@ -46,10 +44,8 @@ public class VolumePrefs { public static final String PREF_ADJUST_NOTIFICATION = "pref_adjust_notification"; public static final boolean DEFAULT_SHOW_HEADERS = true; - public static final boolean DEFAULT_SHOW_FOOTER = true; public static final boolean DEFAULT_ENABLE_AUTOMUTE = true; public static final boolean DEFAULT_ENABLE_SILENT_MODE = true; - public static final boolean DEFAULT_ZEN_FOOTER = true; public static void unregisterCallbacks(Context c, OnSharedPreferenceChangeListener listener) { prefs(c).unregisterOnSharedPreferenceChangeListener(listener); diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java index 5f04aaff90bb..26888130c7f0 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java @@ -103,7 +103,7 @@ public class VolumeUI extends SystemUI { private void setDefaultVolumeController(boolean register) { if (register) { - DndTile.setVisible(mContext, false); + DndTile.setVisible(mContext, true); if (LOGD) Log.d(TAG, "Registering default volume controller"); getVolumeComponent().register(); } else { diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java index 775c87d65ab8..8aded45b8d25 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java +++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java @@ -16,20 +16,12 @@ package com.android.systemui.volume; import android.animation.LayoutTransition; -import android.animation.ValueAnimator; -import android.app.ActivityManager; import android.content.Context; -import android.content.res.Resources; import android.provider.Settings.Global; import android.service.notification.ZenModeConfig; import android.util.AttributeSet; -import android.util.Log; -import android.util.TypedValue; import android.view.View; -import android.widget.CompoundButton; -import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.LinearLayout; -import android.widget.Switch; import android.widget.TextView; import com.android.systemui.R; @@ -38,70 +30,36 @@ import com.android.systemui.statusbar.policy.ZenModeController; import java.util.Objects; /** - * Switch bar + zen mode panel (conditions) attached to the bottom of the volume dialog. + * Zen mode information (and end button) attached to the bottom of the volume dialog. */ public class ZenFooter extends LinearLayout { private static final String TAG = Util.logTag(ZenFooter.class); private final Context mContext; - private final float mSecondaryAlpha; - private final LayoutTransition mLayoutTransition; - private ZenModeController mController; - private Switch mSwitch; - private ZenModePanel mZenModePanel; - private View mZenModePanelButtons; - private View mZenModePanelMoreButton; - private View mZenModePanelDoneButton; - private View mSwitchBar; - private View mSwitchBarIcon; - private View mSummary; private TextView mSummaryLine1; private TextView mSummaryLine2; - private boolean mFooterExpanded; + private View mEndNowButton; private int mZen = -1; private ZenModeConfig mConfig; - private Callback mCallback; + private ZenModeController mController; public ZenFooter(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; - mSecondaryAlpha = getFloat(context.getResources(), R.dimen.volume_secondary_alpha); - mLayoutTransition = new LayoutTransition(); - mLayoutTransition.setDuration(new ValueAnimator().getDuration() / 2); - mLayoutTransition.disableTransitionType(LayoutTransition.DISAPPEARING); - mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING); - } - - private static float getFloat(Resources r, int resId) { - final TypedValue tv = new TypedValue(); - r.getValue(resId, tv, true); - return tv.getFloat(); + setLayoutTransition(new LayoutTransition()); } @Override protected void onFinishInflate() { super.onFinishInflate(); - mSwitchBar = findViewById(R.id.volume_zen_switch_bar); - mSwitchBarIcon = findViewById(R.id.volume_zen_switch_bar_icon); - mSwitch = (Switch) findViewById(R.id.volume_zen_switch); - mZenModePanel = (ZenModePanel) findViewById(R.id.zen_mode_panel); - mZenModePanelButtons = findViewById(R.id.volume_zen_mode_panel_buttons); - mZenModePanelMoreButton = findViewById(R.id.volume_zen_mode_panel_more); - mZenModePanelDoneButton = findViewById(R.id.volume_zen_mode_panel_done); - mSummary = findViewById(R.id.volume_zen_panel_summary); - mSummaryLine1 = (TextView) findViewById(R.id.volume_zen_panel_summary_line_1); - mSummaryLine2 = (TextView) findViewById(R.id.volume_zen_panel_summary_line_2); + mSummaryLine1 = (TextView) findViewById(R.id.volume_zen_summary_line_1); + mSummaryLine2 = (TextView) findViewById(R.id.volume_zen_summary_line_2); + mEndNowButton = findViewById(R.id.volume_zen_end_now); } - public void init(ZenModeController controller, Callback callback) { - mCallback = callback; - mController = controller; - mZenModePanel.init(controller); - mZenModePanel.setEmbedded(true); - mZenModePanel.setCallback(mZenModePanelCallback); - mSwitch.setOnCheckedChangeListener(mCheckedListener); - mController.addCallback(new ZenModeController.Callback() { + public void init(final ZenModeController controller) { + controller.addCallback(new ZenModeController.Callback() { @Override public void onZenChanged(int zen) { setZen(zen); @@ -111,30 +69,15 @@ public class ZenFooter extends LinearLayout { setConfig(config); } }); - mSwitchBar.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mSwitch.setChecked(!mSwitch.isChecked()); - } - }); - mZenModePanelMoreButton.setOnClickListener(new OnClickListener() { + mEndNowButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - if (mCallback != null) { - mCallback.onSettingsClicked(); - } + controller.setZen(Global.ZEN_MODE_OFF, null, TAG); } }); - mZenModePanelDoneButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (mCallback != null) { - mCallback.onDoneClicked(); - } - } - }); - mZen = mController.getZen(); - mConfig = mController.getConfig(); + mZen = controller.getZen(); + mConfig = controller.getConfig(); + mController = controller; update(); } @@ -166,96 +109,17 @@ public class ZenFooter extends LinearLayout { return mZen == Global.ZEN_MODE_NO_INTERRUPTIONS; } - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - setLayoutTransition(null); - setFooterExpanded(false); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - setLayoutTransition(mLayoutTransition); - } - - private boolean setFooterExpanded(boolean expanded) { - if (mFooterExpanded == expanded) return false; - mFooterExpanded = expanded; - update(); - if (mCallback != null) { - mCallback.onFooterExpanded(); - } - return true; - } - - public boolean isFooterExpanded() { - return mFooterExpanded; - } - public void update() { - final boolean isZen = isZen(); - mSwitch.setOnCheckedChangeListener(null); - mSwitch.setChecked(isZen); - mSwitch.setOnCheckedChangeListener(mCheckedListener); - Util.setVisOrGone(mZenModePanel, isZen && mFooterExpanded); - Util.setVisOrGone(mZenModePanelButtons, isZen && mFooterExpanded); - Util.setVisOrGone(mSummary, isZen && !mFooterExpanded); - mSwitchBarIcon.setAlpha(isZen ? 1 : mSecondaryAlpha); final String line1 = isZenPriority() ? mContext.getString(R.string.interruption_level_priority) : isZenAlarms() ? mContext.getString(R.string.interruption_level_alarms) : isZenNone() ? mContext.getString(R.string.interruption_level_none) : null; Util.setText(mSummaryLine1, line1); + final String line2 = ZenModeConfig.getConditionSummary(mContext, mConfig, - ActivityManager.getCurrentUser()); + mController.getCurrentUser()); Util.setText(mSummaryLine2, line2); } - private final ZenModePanel.Callback mZenModePanelCallback = new ZenModePanel.Callback() { - @Override - public void onMoreSettings() { - if (mCallback != null) { - mCallback.onSettingsClicked(); - } - } - - @Override - public void onPrioritySettings() { - if (mCallback != null) { - mCallback.onPrioritySettingsClicked(); - } - } - - @Override - public void onInteraction() { - // noop - } - - @Override - public void onExpanded(boolean expanded) { - // noop - } - }; - - private final OnCheckedChangeListener mCheckedListener = new OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if (D.BUG) Log.d(TAG, "onCheckedChanged " + isChecked); - if (isChecked != isZen()) { - final int newZen = isChecked ? Global.ZEN_MODE_ALARMS : Global.ZEN_MODE_OFF; - mZen = newZen; // this one's optimistic - setFooterExpanded(isChecked); - mController.setZen(newZen, null, TAG); - } - } - }; - - public interface Callback { - void onFooterExpanded(); - void onSettingsClicked(); - void onDoneClicked(); - void onPrioritySettingsClicked(); - } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java index 1b563dcbfa76..9f9c9ac87a25 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java +++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java @@ -41,8 +41,6 @@ import android.util.MathUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.animation.AnimationUtils; -import android.view.animation.Interpolator; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ImageView; @@ -85,22 +83,14 @@ public class ZenModePanel extends LinearLayout { private final H mHandler = new H(); private final ZenPrefs mPrefs; private final IconPulser mIconPulser; - private final int mSubheadWarningColor; - private final int mSubheadColor; - private final Interpolator mInterpolator; private final TransitionHelper mTransitionHelper = new TransitionHelper(); private final Uri mForeverId; private String mTag = TAG + "/" + Integer.toHexString(System.identityHashCode(this)); private SegmentedButtons mZenButtons; - private ViewGroup mZenButtonsContainer; - private View mZenSubhead; - private TextView mZenSubheadCollapsed; - private TextView mZenSubheadExpanded; - private View mZenEmbeddedDivider; - private View mMoreSettings; private View mZenIntroduction; + private TextView mZenIntroductionMessage; private View mZenIntroductionConfirm; private View mZenIntroductionCustomize; private LinearLayout mZenConditions; @@ -113,7 +103,6 @@ public class ZenModePanel extends LinearLayout { private int mFirstConditionIndex; private boolean mRequestingConditions; private Condition mExitCondition; - private String mExitConditionText; private int mBucketIndex = -1; private boolean mExpanded; private boolean mHidden; @@ -123,7 +112,6 @@ public class ZenModePanel extends LinearLayout { private Condition mSessionExitCondition; private Condition[] mConditions; private Condition mTimeCondition; - private boolean mEmbedded; public ZenModePanel(Context context, AttributeSet attrs) { super(context, attrs); @@ -131,10 +119,6 @@ public class ZenModePanel extends LinearLayout { mPrefs = new ZenPrefs(); mInflater = LayoutInflater.from(mContext.getApplicationContext()); mIconPulser = new IconPulser(mContext); - mSubheadWarningColor = context.getColor(R.color.system_warning_color); - mSubheadColor = context.getColor(R.color.qs_subhead); - mInterpolator = AnimationUtils.loadInterpolator(mContext, - com.android.internal.R.interpolator.fast_out_slow_in); mForeverId = Condition.newId(mContext).appendPath("forever").build(); if (DEBUG) Log.d(mTag, "new ZenModePanel"); } @@ -149,25 +133,13 @@ public class ZenModePanel extends LinearLayout { pw.print(" mExpanded="); pw.println(mExpanded); pw.print(" mSessionZen="); pw.println(mSessionZen); pw.print(" mAttachedZen="); pw.println(mAttachedZen); - pw.print(" mEmbedded="); pw.println(mEmbedded); + pw.print(" mConfirmedPriorityIntroduction="); + pw.println(mPrefs.mConfirmedPriorityIntroduction); + pw.print(" mConfirmedSilenceIntroduction="); + pw.println(mPrefs.mConfirmedSilenceIntroduction); mTransitionHelper.dump(fd, pw, args); } - public void setEmbedded(boolean embedded) { - if (mEmbedded == embedded) return; - mEmbedded = embedded; - mZenButtonsContainer.setLayoutTransition(mEmbedded ? null : newLayoutTransition(null)); - setLayoutTransition(mEmbedded ? null : newLayoutTransition(null)); - if (mEmbedded) { - mZenButtonsContainer.setBackground(null); - } else { - mZenButtonsContainer.setBackgroundResource(R.drawable.qs_background_secondary); - } - mZenButtons.getChildAt(3).setVisibility(mEmbedded ? GONE : VISIBLE); - mZenEmbeddedDivider.setVisibility(mEmbedded ? VISIBLE : GONE); - updateWidgets(); - } - @Override protected void onFinishInflate() { super.onFinishInflate(); @@ -179,37 +151,10 @@ public class ZenModePanel extends LinearLayout { Global.ZEN_MODE_ALARMS); mZenButtons.addButton(R.string.interruption_level_priority_twoline, Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS); - mZenButtons.addButton(R.string.interruption_level_all, Global.ZEN_MODE_OFF); mZenButtons.setCallback(mZenButtonsCallback); - mZenButtonsContainer = (ViewGroup) findViewById(R.id.zen_buttons_container); - mZenButtonsContainer.setLayoutTransition(newLayoutTransition(null)); - - mZenSubhead = findViewById(R.id.zen_subhead); - mZenEmbeddedDivider = findViewById(R.id.zen_embedded_divider); - - mZenSubheadCollapsed = (TextView) findViewById(R.id.zen_subhead_collapsed); - mZenSubheadCollapsed.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - setExpanded(true); - } - }); - Interaction.register(mZenSubheadCollapsed, mInteractionCallback); - - mZenSubheadExpanded = (TextView) findViewById(R.id.zen_subhead_expanded); - Interaction.register(mZenSubheadExpanded, mInteractionCallback); - - mMoreSettings = findViewById(R.id.zen_more_settings); - mMoreSettings.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - fireMoreSettings(); - } - }); - Interaction.register(mMoreSettings, mInteractionCallback); - mZenIntroduction = findViewById(R.id.zen_introduction); + mZenIntroductionMessage = (TextView) findViewById(R.id.zen_introduction_message); mZenIntroductionConfirm = findViewById(R.id.zen_introduction_confirm); mZenIntroductionConfirm.setOnClickListener(new OnClickListener() { @Override @@ -230,25 +175,25 @@ public class ZenModePanel extends LinearLayout { mZenConditions = (LinearLayout) findViewById(R.id.zen_conditions); - setLayoutTransition(newLayoutTransition(mTransitionHelper)); } private void confirmZenIntroduction() { - if (DEBUG) Log.d(TAG, "confirmZenIntroduction"); - Prefs.putBoolean(mContext, Prefs.Key.DND_CONFIRMED_PRIORITY_INTRODUCTION, true); + final String prefKey = prefKeyForConfirmation(getSelectedZen(Global.ZEN_MODE_OFF)); + if (prefKey == null) return; + if (DEBUG) Log.d(TAG, "confirmZenIntroduction " + prefKey); + Prefs.putBoolean(mContext, prefKey, true); mHandler.sendEmptyMessage(H.UPDATE_WIDGETS); } - private LayoutTransition newLayoutTransition(TransitionListener listener) { - final LayoutTransition transition = new LayoutTransition(); - transition.disableTransitionType(LayoutTransition.DISAPPEARING); - transition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING); - transition.disableTransitionType(LayoutTransition.APPEARING); - transition.setInterpolator(LayoutTransition.CHANGE_APPEARING, mInterpolator); - if (listener != null) { - transition.addTransitionListener(listener); + private static String prefKeyForConfirmation(int zen) { + switch (zen) { + case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: + return Prefs.Key.DND_CONFIRMED_PRIORITY_INTRODUCTION; + case Global.ZEN_MODE_NO_INTERRUPTIONS: + return Prefs.Key.DND_CONFIRMED_SILENCE_INTRODUCTION; + default: + return null; } - return transition; } @Override @@ -260,7 +205,6 @@ public class ZenModePanel extends LinearLayout { mSessionZen = mAttachedZen; mTransitionHelper.clear(); setSessionExitCondition(copy(mExitCondition)); - refreshExitConditionText(); updateWidgets(); setRequestingConditions(!mHidden); } @@ -274,9 +218,6 @@ public class ZenModePanel extends LinearLayout { mAttachedZen = -1; mSessionZen = -1; setSessionExitCondition(null); - if (!mEmbedded) { - setExpanded(false); - } setRequestingConditions(false); mTransitionHelper.clear(); } @@ -359,7 +300,6 @@ public class ZenModePanel extends LinearLayout { for (int i = 0; i < mMaxConditions; i++) { mZenConditions.addView(mInflater.inflate(R.layout.zen_mode_condition, this, false)); } - refreshExitConditionText(); mSessionZen = getSelectedZen(-1); handleUpdateManualRule(mController.getManualRule()); if (DEBUG) Log.d(mTag, "init mExitCondition=" + mExitCondition); @@ -375,7 +315,6 @@ public class ZenModePanel extends LinearLayout { if (Objects.equals(mExitCondition, exitCondition)) return; mExitCondition = exitCondition; if (DEBUG) Log.d(mTag, "mExitCondition=" + getConditionId(mExitCondition)); - refreshExitConditionText(); updateWidgets(); } @@ -395,10 +334,6 @@ public class ZenModePanel extends LinearLayout { return condition == null ? null : condition.copy(); } - private void refreshExitConditionText() { - mExitConditionText = getExitConditionText(mContext, mExitCondition); - } - public static String getExitConditionText(Context context, Condition exitCondition) { if (exitCondition == null) { return foreverSummary(context); @@ -430,7 +365,7 @@ public class ZenModePanel extends LinearLayout { private void handleUpdateZen(int zen) { if (mSessionZen != -1 && mSessionZen != zen) { - setExpanded(mEmbedded && isShown() || !mEmbedded && zen != Global.ZEN_MODE_OFF); + setExpanded(isShown()); mSessionZen = zen; } mZenButtons.setSelectedValue(zen); @@ -480,30 +415,18 @@ public class ZenModePanel extends LinearLayout { return; } final int zen = getSelectedZen(Global.ZEN_MODE_OFF); - final boolean zenOff = zen == Global.ZEN_MODE_OFF; final boolean zenImportant = zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS; - final boolean expanded = !mHidden && mExpanded; - final boolean conditions = mEmbedded || !zenOff && expanded; - final boolean introduction = conditions && zenImportant && !mPrefs.mConfirmedIntroduction; + final boolean introduction = (zenImportant && !mPrefs.mConfirmedPriorityIntroduction + || zenNone && !mPrefs.mConfirmedSilenceIntroduction); mZenButtons.setVisibility(mHidden ? GONE : VISIBLE); - mZenSubhead.setVisibility(!mHidden && !zenOff && !mEmbedded ? VISIBLE : GONE); - mZenSubheadExpanded.setVisibility(expanded ? VISIBLE : GONE); - mZenSubheadCollapsed.setVisibility(!expanded ? VISIBLE : GONE); - mMoreSettings.setVisibility(zenImportant && expanded ? VISIBLE : GONE); - mZenConditions.setVisibility(conditions ? VISIBLE : GONE); - - if (zenNone) { - mZenSubheadExpanded.setText(R.string.zen_no_interruptions_with_warning); - mZenSubheadCollapsed.setText(mExitConditionText); - } else if (zenImportant) { - mZenSubheadExpanded.setText(R.string.zen_important_interruptions); - mZenSubheadCollapsed.setText(mExitConditionText); - } - mZenSubheadExpanded.setTextColor(zenNone && mPrefs.isNoneDangerous() - ? mSubheadWarningColor : mSubheadColor); mZenIntroduction.setVisibility(introduction ? VISIBLE : GONE); + if (introduction) { + mZenIntroductionMessage.setText(zenImportant ? R.string.zen_priority_introduction + : R.string.zen_silence_introduction); + mZenIntroductionCustomize.setVisibility(zenImportant ? VISIBLE : GONE); + } } private static Condition parseExistingTimeCondition(Context context, Condition condition) { @@ -761,13 +684,13 @@ public class ZenModePanel extends LinearLayout { String modeText; switch(zen) { case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: - modeText = mContext.getString(R.string.zen_important_interruptions); + modeText = mContext.getString(R.string.interruption_level_priority); break; case Global.ZEN_MODE_NO_INTERRUPTIONS: - modeText = mContext.getString(R.string.zen_no_interruptions); + modeText = mContext.getString(R.string.interruption_level_none); break; case Global.ZEN_MODE_ALARMS: - modeText = mContext.getString(R.string.zen_alarms); + modeText = mContext.getString(R.string.interruption_level_alarms); break; default: return; @@ -837,12 +760,6 @@ public class ZenModePanel extends LinearLayout { setSessionExitCondition(copy(condition)); } - private void fireMoreSettings() { - if (mCallback != null) { - mCallback.onMoreSettings(); - } - } - private void fireInteraction() { if (mCallback != null) { mCallback.onInteraction(); @@ -887,7 +804,6 @@ public class ZenModePanel extends LinearLayout { } public interface Callback { - void onMoreSettings(); void onPrioritySettings(); void onInteraction(); void onExpanded(boolean expanded); @@ -907,7 +823,8 @@ public class ZenModePanel extends LinearLayout { private int mMinuteIndex; private int mNoneSelected; - private boolean mConfirmedIntroduction; + private boolean mConfirmedPriorityIntroduction; + private boolean mConfirmedSilenceIntroduction; private ZenPrefs() { mNoneDangerousThreshold = mContext.getResources() @@ -915,11 +832,8 @@ public class ZenModePanel extends LinearLayout { Prefs.registerListener(mContext, this); updateMinuteIndex(); updateNoneSelected(); - updateConfirmedIntroduction(); - } - - public boolean isNoneDangerous() { - return mNoneSelected < mNoneDangerousThreshold; + updateConfirmedPriorityIntroduction(); + updateConfirmedSilenceIntroduction(); } public void trackNoneSelected() { @@ -945,7 +859,8 @@ public class ZenModePanel extends LinearLayout { public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { updateMinuteIndex(); updateNoneSelected(); - updateConfirmedIntroduction(); + updateConfirmedPriorityIntroduction(); + updateConfirmedSilenceIntroduction(); } private void updateMinuteIndex() { @@ -968,12 +883,22 @@ public class ZenModePanel extends LinearLayout { return MathUtils.constrain(noneSelected, 0, Integer.MAX_VALUE); } - private void updateConfirmedIntroduction() { + private void updateConfirmedPriorityIntroduction() { final boolean confirmed = Prefs.getBoolean(mContext, Prefs.Key.DND_CONFIRMED_PRIORITY_INTRODUCTION, false); - if (confirmed == mConfirmedIntroduction) return; - mConfirmedIntroduction = confirmed; - if (DEBUG) Log.d(mTag, "Confirmed introduction: " + mConfirmedIntroduction); + if (confirmed == mConfirmedPriorityIntroduction) return; + mConfirmedPriorityIntroduction = confirmed; + if (DEBUG) Log.d(mTag, "Confirmed priority introduction: " + + mConfirmedPriorityIntroduction); + } + + private void updateConfirmedSilenceIntroduction() { + final boolean confirmed = Prefs.getBoolean(mContext, + Prefs.Key.DND_CONFIRMED_SILENCE_INTRODUCTION, false); + if (confirmed == mConfirmedSilenceIntroduction) return; + mConfirmedSilenceIntroduction = confirmed; + if (DEBUG) Log.d(mTag, "Confirmed silence introduction: " + + mConfirmedSilenceIntroduction); } } @@ -981,12 +906,16 @@ public class ZenModePanel extends LinearLayout { @Override public void onSelected(final Object value) { if (value != null && mZenButtons.isShown() && isAttachedToWindow()) { - if (DEBUG) Log.d(mTag, "mZenButtonsCallback selected=" + value); + final int zen = (Integer) value; + if (DEBUG) Log.d(mTag, "mZenButtonsCallback selected=" + zen); final Uri realConditionId = getRealConditionId(mSessionExitCondition); AsyncTask.execute(new Runnable() { @Override public void run() { - mController.setZen((Integer) value, realConditionId, TAG + ".selectZen"); + mController.setZen(zen, realConditionId, TAG + ".selectZen"); + if (zen != Global.ZEN_MODE_OFF) { + Prefs.putInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, zen); + } } }); } diff --git a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java index 38827d09c99f..d0b5898076fc 100644 --- a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java +++ b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java @@ -41,12 +41,18 @@ class DisplayAdjustmentUtils { 0, 0, 0, 1 }; - /** Matrix and offset used for value-only display inversion. */ + /** + * Matrix and offset used for luminance inversion. Represents a transform + * from RGB to YIQ color space, rotation around the Y axis by 180 degrees, + * transform back to RGB color space, and subtraction from 1. The last row + * represents a non-multiplied addition, see surfaceflinger's ProgramCache + * for full implementation details. + */ private static final float[] INVERSION_MATRIX_VALUE_ONLY = new float[] { - 0, -.5f, -.5f, 0, - -.5f, 0, -.5f, 0, - -.5f, -.5f, 0, 0, - 1, 1, 1, 1 + 0.402f, -0.598f, -0.599f, 0, + -1.174f, -0.174f, -1.175f, 0, + -0.228f, -0.228f, 0.772f, 0, + 1, 1, 1, 1 }; /** Default inversion mode for display color correction. */ diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 0e3867d6ff5c..745c1906c46c 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -461,7 +461,7 @@ class AlarmManagerService extends SystemService { // to run during this time are placed in mPendingWhileIdleAlarms Alarm mPendingIdleUntil = null; Alarm mNextWakeFromIdle = null; - final ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>(); + ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>(); public AlarmManagerService(Context context) { super(context); @@ -567,10 +567,14 @@ class AlarmManagerService extends SystemService { void restorePendingWhileIdleAlarmsLocked() { // Bring pending alarms back into the main list. - final long nowElapsed = SystemClock.elapsedRealtime(); - for (int i=mPendingWhileIdleAlarms.size() - 1; i >= 0 && mPendingIdleUntil == null; i--) { - Alarm a = mPendingWhileIdleAlarms.remove(i); - reAddAlarmLocked(a, nowElapsed, false); + if (mPendingWhileIdleAlarms.size() > 0) { + ArrayList<Alarm> alarms = mPendingWhileIdleAlarms; + mPendingWhileIdleAlarms = new ArrayList<>(); + final long nowElapsed = SystemClock.elapsedRealtime(); + for (int i=alarms.size() - 1; i >= 0; i--) { + Alarm a = alarms.get(i); + reAddAlarmLocked(a, nowElapsed, false); + } } // Reschedule everything. @@ -1053,11 +1057,16 @@ class AlarmManagerService extends SystemService { dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC, sdf); } } - if (mPendingIdleUntil != null) { + if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) { pw.println(); pw.println("Idle mode state:"); - pw.print(" Idling until: "); pw.println(mPendingIdleUntil); - mPendingIdleUntil.dump(pw, " ", nowRTC, nowELAPSED, sdf); + pw.print(" Idling until: "); + if (mPendingIdleUntil != null) { + pw.println(mPendingIdleUntil); + mPendingIdleUntil.dump(pw, " ", nowRTC, nowELAPSED, sdf); + } else { + pw.println("null"); + } pw.println(" Pending alarms:"); dumpAlarmList(pw, mPendingWhileIdleAlarms, " ", nowELAPSED, nowRTC, sdf); } diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java new file mode 100644 index 000000000000..b7bc0f02ea4f --- /dev/null +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -0,0 +1,879 @@ +/* + * Copyright (C) 2015 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; + +import android.app.AlarmManager; +import android.app.PendingIntent; +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.Sensor; +import android.hardware.SensorManager; +import android.hardware.TriggerEvent; +import android.hardware.TriggerEventListener; +import android.hardware.display.DisplayManager; +import android.net.INetworkPolicyManager; +import android.os.Binder; +import android.os.Environment; +import android.os.FileUtils; +import android.os.Handler; +import android.os.IDeviceIdleController; +import android.os.Looper; +import android.os.Message; +import android.os.PowerManager; +import android.os.PowerManagerInternal; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemClock; +import android.os.UserHandle; +import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.Slog; +import android.util.SparseBooleanArray; +import android.util.TimeUtils; +import android.util.Xml; +import android.view.Display; +import com.android.internal.app.IBatteryStats; +import com.android.internal.os.AtomicFile; +import com.android.internal.os.BackgroundThread; +import com.android.internal.util.FastXmlSerializer; +import com.android.internal.util.XmlUtils; +import com.android.server.am.BatteryStatsService; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * Keeps track of device idleness and drives low power mode based on that. + */ +public class DeviceIdleController extends SystemService { + private static final String TAG = "DeviceIdleController"; + + public static final String SERVICE_NAME = "deviceidle"; + + private static final String ACTION_STEP_IDLE_STATE = + "com.android.server.device_idle.STEP_IDLE_STATE"; + + // TODO: These need to be moved to system settings. + + /** + * This is the time, after becoming inactive, at which we start looking at the + * motion sensor to determine if the device is being left alone. We don't do this + * immediately after going inactive just because we don't want to be continually running + * the significant motion sensor whenever the screen is off. + */ + private static final long DEFAULT_INACTIVE_TIMEOUT = 30*60*1000L; + /** + * This is the time, after seeing motion, that we wait after becoming inactive from + * that until we start looking for motion again. + */ + private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = 10*60*1000L; + /** + * This is the time, after the inactive timeout elapses, that we will wait looking + * for significant motion until we truly consider the device to be idle. + */ + private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = 30*60*1000L; + /** + * This is the initial time, after being idle, that we will allow ourself to be back + * in the IDLE_PENDING state allowing the system to run normally until we return to idle. + */ + private static final long DEFAULT_IDLE_PENDING_TIMEOUT = 5*60*1000L; + /** + * Maximum pending idle timeout (time spent running) we will be allowed to use. + */ + private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT = 10*60*1000L; + /** + * Scaling factor to apply to current pending idle timeout each time we cycle through + * that state. + */ + private static final float DEFAULT_IDLE_PENDING_FACTOR = 2f; + /** + * This is the initial time that we want to sit in the idle state before waking up + * again to return to pending idle and allowing normal work to run. + */ + private static final long DEFAULT_IDLE_TIMEOUT = 60*60*1000L; + /** + * Maximum idle duration we will be allowed to use. + */ + private static final long DEFAULT_MAX_IDLE_TIMEOUT = 6*60*60*1000L; + /** + * Scaling factor to apply to current idle timeout each time we cycle through that state. + */ + private static final float DEFAULT_IDLE_FACTOR = 2f; + /** + * This is the minimum time we will allow until the next upcoming alarm for us to + * actually go in to idle mode. + */ + private static final long DEFAULT_MIN_TIME_TO_ALARM = 60*60*1000L; + + private AlarmManager mAlarmManager; + private IBatteryStats mBatteryStats; + private PowerManagerInternal mLocalPowerManager; + private INetworkPolicyManager mNetworkPolicyManager; + private DisplayManager mDisplayManager; + private SensorManager mSensorManager; + private Sensor mSigMotionSensor; + private PendingIntent mAlarmIntent; + private Intent mIdleIntent; + private Display mCurDisplay; + private boolean mScreenOn; + private boolean mCharging; + private boolean mSigMotionActive; + + /** Device is currently active. */ + private static final int STATE_ACTIVE = 0; + /** Device is inactve (screen off, no motion) and we are waiting to for idle. */ + private static final int STATE_INACTIVE = 1; + /** Device is past the initial inactive period, and waiting for the next idle period. */ + private static final int STATE_IDLE_PENDING = 2; + /** Device is in the idle state, trying to stay asleep as much as possible. */ + private static final int STATE_IDLE = 3; + /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */ + private static final int STATE_IDLE_MAINTENANCE = 4; + private static String stateToString(int state) { + switch (state) { + case STATE_ACTIVE: return "ACTIVE"; + case STATE_INACTIVE: return "INACTIVE"; + case STATE_IDLE_PENDING: return "IDLE_PENDING"; + case STATE_IDLE: return "IDLE"; + case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE"; + default: return Integer.toString(state); + } + } + + private int mState; + + private long mInactiveTimeout; + private long mNextAlarmTime; + private long mNextIdlePendingDelay; + private long mNextIdleDelay; + + public final AtomicFile mConfigFile; + + /** + * Package names the system has white-listed to opt out of power save restrictions. + */ + private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>(); + + /** + * Package names the user has white-listed to opt out of power save restrictions. + */ + private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>(); + + /** + * UIDs that have been white-listed to opt out of power save restrictions. + */ + private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray(); + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { + int plugged = intent.getIntExtra("plugged", 0); + updateChargingLocked(plugged != 0); + } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) { + synchronized (DeviceIdleController.this) { + stepIdleStateLocked(); + } + } + } + }; + + private final DisplayManager.DisplayListener mDisplayListener + = new DisplayManager.DisplayListener() { + @Override public void onDisplayAdded(int displayId) { + } + + @Override public void onDisplayRemoved(int displayId) { + } + + @Override public void onDisplayChanged(int displayId) { + if (displayId == Display.DEFAULT_DISPLAY) { + synchronized (DeviceIdleController.this) { + updateDisplayLocked(); + } + } + } + }; + + private final TriggerEventListener mSigMotionListener = new TriggerEventListener() { + @Override public void onTrigger(TriggerEvent event) { + synchronized (DeviceIdleController.this) { + significantMotionLocked(); + } + } + }; + + static final int MSG_WRITE_CONFIG = 1; + static final int MSG_REPORT_IDLE_ON = 2; + static final int MSG_REPORT_IDLE_OFF = 3; + static final int MSG_REPORT_ACTIVE = 4; + + final class MyHandler extends Handler { + MyHandler(Looper looper) { + super(looper); + } + + @Override public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_WRITE_CONFIG: { + handleWriteConfigFile(); + } break; + case MSG_REPORT_IDLE_ON: { + mLocalPowerManager.setDeviceIdleMode(true); + try { + mNetworkPolicyManager.setDeviceIdleMode(true); + mBatteryStats.noteDeviceIdleMode(true, false, false); + } catch (RemoteException e) { + } + getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); + } break; + case MSG_REPORT_IDLE_OFF: { + mLocalPowerManager.setDeviceIdleMode(false); + try { + mNetworkPolicyManager.setDeviceIdleMode(false); + mBatteryStats.noteDeviceIdleMode(false, false, false); + } catch (RemoteException e) { + } + getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); + } break; + case MSG_REPORT_ACTIVE: { + boolean fromMotion = msg.arg1 != 0; + boolean needBroadcast = msg.arg2 != 0; + mLocalPowerManager.setDeviceIdleMode(false); + try { + mNetworkPolicyManager.setDeviceIdleMode(false); + mBatteryStats.noteDeviceIdleMode(false, !fromMotion, fromMotion); + } catch (RemoteException e) { + } + if (needBroadcast) { + getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); + } + } break; + } + } + } + + final MyHandler mHandler; + + private final class BinderService extends IDeviceIdleController.Stub { + @Override public void addPowerSaveWhitelistApp(String name) { + getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, + null); + addPowerSaveWhitelistAppInternal(name); + } + + @Override public void removePowerSaveWhitelistApp(String name) { + getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, + null); + removePowerSaveWhitelistAppInternal(name); + } + + @Override public String[] getSystemPowerWhitelist() { + return getSystemPowerWhitelistInternal(); + } + + @Override public String[] getFullPowerWhitelist() { + return getFullPowerWhitelistInternal(); + } + + @Override public int[] getAppIdWhitelist() { + return getAppIdWhitelistInternal(); + } + + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + DeviceIdleController.this.dump(fd, pw, args); + } + } + + public DeviceIdleController(Context context) { + super(context); + mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml")); + mHandler = new MyHandler(BackgroundThread.getHandler().getLooper()); + } + + private static File getSystemDir() { + return new File(Environment.getDataDirectory(), "system"); + } + + @Override + public void onStart() { + final PackageManager pm = getContext().getPackageManager(); + + synchronized (this) { + SystemConfig sysConfig = SystemConfig.getInstance(); + ArraySet<String> allowPower = sysConfig.getAllowInPowerSave(); + for (int i=0; i<allowPower.size(); i++) { + String pkg = allowPower.valueAt(i); + try { + ApplicationInfo ai = pm.getApplicationInfo(pkg, 0); + if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) { + mPowerSaveWhitelistApps.put(ai.packageName, + UserHandle.getAppId(ai.uid)); + } + } catch (PackageManager.NameNotFoundException e) { + } + } + + readConfigFileLocked(); + updateWhitelistAppIdsLocked(); + + mScreenOn = true; + // Start out assuming we are charging. If we aren't, we will at least get + // a battery update the next time the level drops. + mCharging = true; + mState = STATE_ACTIVE; + mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT; + } + + publishBinderService(SERVICE_NAME, new BinderService()); + } + + @Override + public void onBootPhase(int phase) { + if (phase == PHASE_SYSTEM_SERVICES_READY) { + synchronized (this) { + mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); + mBatteryStats = BatteryStatsService.getService(); + mLocalPowerManager = getLocalService(PowerManagerInternal.class); + mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface( + ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)); + mDisplayManager = (DisplayManager) getContext().getSystemService( + Context.DISPLAY_SERVICE); + mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); + mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION); + + Intent intent = new Intent(ACTION_STEP_IDLE_STATE) + .setPackage("android") + .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0); + + mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); + mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_BATTERY_CHANGED); + filter.addAction(ACTION_STEP_IDLE_STATE); + getContext().registerReceiver(mReceiver, filter); + + mDisplayManager.registerDisplayListener(mDisplayListener, null); + updateDisplayLocked(); + } + } + } + + public boolean addPowerSaveWhitelistAppInternal(String name) { + synchronized (this) { + try { + ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name, 0); + if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) { + reportPowerSaveWhitelistChangedLocked(); + updateWhitelistAppIdsLocked(); + writeConfigFileLocked(); + } + return true; + } catch (PackageManager.NameNotFoundException e) { + return false; + } + } + } + + public boolean removePowerSaveWhitelistAppInternal(String name) { + synchronized (this) { + if (mPowerSaveWhitelistUserApps.remove(name) != null) { + reportPowerSaveWhitelistChangedLocked(); + updateWhitelistAppIdsLocked(); + writeConfigFileLocked(); + return true; + } + } + return false; + } + + public String[] getSystemPowerWhitelistInternal() { + synchronized (this) { + int size = mPowerSaveWhitelistApps.size(); + String[] apps = new String[size]; + for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) { + apps[i] = mPowerSaveWhitelistApps.keyAt(i); + } + return apps; + } + } + + public String[] getFullPowerWhitelistInternal() { + synchronized (this) { + int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size(); + String[] apps = new String[size]; + int cur = 0; + for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) { + apps[cur] = mPowerSaveWhitelistApps.keyAt(i); + cur++; + } + for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) { + apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i); + cur++; + } + return apps; + } + } + + public int[] getAppIdWhitelistInternal() { + synchronized (this) { + int size = mPowerSaveWhitelistAppIds.size(); + int[] appids = new int[size]; + for (int i = 0; i < size; i++) { + appids[i] = mPowerSaveWhitelistAppIds.keyAt(i); + } + return appids; + } + } + + void updateDisplayLocked() { + mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); + // We consider any situation where the display is showing something to be it on, + // because if there is anything shown we are going to be updating it at some + // frequency so can't be allowed to go into deep sleeps. + boolean screenOn = mCurDisplay.getState() != Display.STATE_OFF;; + if (!screenOn && mScreenOn) { + mScreenOn = false; + becomeInactiveIfAppropriateLocked(); + } else if (screenOn) { + mScreenOn = true; + becomeActiveLocked("screen"); + } + } + + void updateChargingLocked(boolean charging) { + if (!charging && mCharging) { + mCharging = false; + becomeInactiveIfAppropriateLocked(); + } else if (charging) { + mCharging = charging; + becomeActiveLocked("charging"); + } + } + + void scheduleReportActiveLocked(boolean fromMotion) { + Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, fromMotion ? 1 : 0, + mState == STATE_IDLE ? 1 : 0); + mHandler.sendMessage(msg); + } + + void becomeActiveLocked(String reason) { + if (mState != STATE_ACTIVE) { + EventLogTags.writeDeviceIdle(STATE_ACTIVE, reason); + scheduleReportActiveLocked(false); + mState = STATE_ACTIVE; + mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT; + mNextIdlePendingDelay = 0; + mNextIdleDelay = 0; + cancelAlarmLocked(); + stopMonitoringSignificantMotion(); + } + } + + void becomeInactiveIfAppropriateLocked() { + if (!mScreenOn && !mCharging && mState == STATE_ACTIVE) { + // Screen has turned off; we are now going to become inactive and start + // waiting to see if we will ultimately go idle. + mState = STATE_INACTIVE; + mNextIdlePendingDelay = 0; + mNextIdleDelay = 0; + scheduleAlarmLocked(mInactiveTimeout, false); + EventLogTags.writeDeviceIdle(mState, "no activity"); + } + } + + void stepIdleStateLocked() { + EventLogTags.writeDeviceIdleStep(); + + final long now = SystemClock.elapsedRealtime(); + if ((now+DEFAULT_MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) { + // Whoops, there is an upcoming alarm. We don't actually want to go idle. + if (mState != STATE_ACTIVE) { + becomeActiveLocked("alarm"); + } + return; + } + + switch (mState) { + case STATE_INACTIVE: + // We have now been inactive long enough, it is time to start looking + // for significant motion and sleep some more while doing so. + startMonitoringSignificantMotion(); + scheduleAlarmLocked(DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT, false); + // Reset the upcoming idle delays. + mNextIdlePendingDelay = DEFAULT_IDLE_PENDING_TIMEOUT; + mNextIdleDelay = DEFAULT_IDLE_TIMEOUT; + mState = STATE_IDLE_PENDING; + EventLogTags.writeDeviceIdle(mState, "step"); + break; + case STATE_IDLE_PENDING: + case STATE_IDLE_MAINTENANCE: + // We have been waiting to become idle, and now it is time! This is the + // only case where we want to use a wakeup alarm, because we do want to + // drag the device out of its sleep state in this case to do the next + // scheduled work. + scheduleAlarmLocked(mNextIdleDelay, true); + mNextIdleDelay = (long)(mNextIdleDelay*DEFAULT_IDLE_FACTOR); + if (mNextIdleDelay > DEFAULT_MAX_IDLE_TIMEOUT) { + mNextIdleDelay = DEFAULT_MAX_IDLE_TIMEOUT; + } + mState = STATE_IDLE; + EventLogTags.writeDeviceIdle(mState, "step"); + mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON); + break; + case STATE_IDLE: + // We have been idling long enough, now it is time to do some work. + scheduleAlarmLocked(mNextIdlePendingDelay, false); + mNextIdlePendingDelay = (long)(mNextIdlePendingDelay*DEFAULT_IDLE_PENDING_FACTOR); + if (mNextIdlePendingDelay > DEFAULT_MAX_IDLE_PENDING_TIMEOUT) { + mNextIdlePendingDelay = DEFAULT_MAX_IDLE_PENDING_TIMEOUT; + } + mState = STATE_IDLE_MAINTENANCE; + EventLogTags.writeDeviceIdle(mState, "step"); + mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF); + break; + } + } + + void significantMotionLocked() { + // When the sensor goes off, its trigger is automatically removed. + mSigMotionActive = false; + // The device is not yet active, so we want to go back to the pending idle + // state to wait again for no motion. Note that we only monitor for significant + // motion after moving out of the inactive state, so no need to worry about that. + if (mState != STATE_ACTIVE) { + scheduleReportActiveLocked(true); + mState = STATE_ACTIVE; + mInactiveTimeout = DEFAULT_MOTION_INACTIVE_TIMEOUT; + EventLogTags.writeDeviceIdle(mState, "motion"); + becomeInactiveIfAppropriateLocked(); + } + } + + void startMonitoringSignificantMotion() { + if (mSigMotionSensor != null && !mSigMotionActive) { + mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor); + mSigMotionActive = true; + } + } + + void stopMonitoringSignificantMotion() { + if (mSigMotionActive) { + mSensorManager.cancelTriggerSensor(mSigMotionListener, mSigMotionSensor); + mSigMotionActive = false; + } + } + + void cancelAlarmLocked() { + if (mNextAlarmTime != 0) { + mNextAlarmTime = 0; + mAlarmManager.cancel(mAlarmIntent); + } + } + + void scheduleAlarmLocked(long delay, boolean idleUntil) { + if (mSigMotionSensor == null) { + // If there is no significant motion sensor on this device, then we won't schedule + // alarms, because we can't determine if the device is not moving. This effectively + // turns off normal exeuction of device idling, although it is still possible to + // manually poke it by pretending like the alarm is going off. + return; + } + mNextAlarmTime = SystemClock.elapsedRealtime() + delay; + if (idleUntil) { + mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP, + mNextAlarmTime, mAlarmIntent); + } else { + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, + mNextAlarmTime, mAlarmIntent); + } + } + + private void updateWhitelistAppIdsLocked() { + mPowerSaveWhitelistAppIds.clear(); + for (int i=0; i<mPowerSaveWhitelistApps.size(); i++) { + mPowerSaveWhitelistAppIds.put(mPowerSaveWhitelistApps.valueAt(i), true); + } + for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) { + mPowerSaveWhitelistAppIds.put(mPowerSaveWhitelistUserApps.valueAt(i), true); + } + } + + private void reportPowerSaveWhitelistChangedLocked() { + Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + getContext().sendBroadcast(intent); + } + + void readConfigFileLocked() { + Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile()); + mPowerSaveWhitelistUserApps.clear(); + FileInputStream stream; + try { + stream = mConfigFile.openRead(); + } catch (FileNotFoundException e) { + return; + } + try { + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(stream, null); + readConfigFileLocked(parser); + } catch (XmlPullParserException e) { + } finally { + try { + stream.close(); + } catch (IOException e) { + } + } + + } + + private void readConfigFileLocked(XmlPullParser parser) { + final PackageManager pm = getContext().getPackageManager(); + + try { + int type; + while ((type = parser.next()) != XmlPullParser.START_TAG + && type != XmlPullParser.END_DOCUMENT) { + ; + } + + if (type != XmlPullParser.START_TAG) { + throw new IllegalStateException("no start tag found"); + } + + int outerDepth = parser.getDepth(); + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("wl")) { + String name = parser.getAttributeValue(null, "n"); + if (name != null) { + try { + ApplicationInfo ai = pm.getApplicationInfo(name, 0); + mPowerSaveWhitelistUserApps.put(ai.packageName, + UserHandle.getAppId(ai.uid)); + } catch (PackageManager.NameNotFoundException e) { + } + } + } else { + Slog.w(TAG, "Unknown element under <config>: " + + parser.getName()); + XmlUtils.skipCurrentTag(parser); + } + } + + } catch (IllegalStateException e) { + Slog.w(TAG, "Failed parsing config " + e); + } catch (NullPointerException e) { + Slog.w(TAG, "Failed parsing config " + e); + } catch (NumberFormatException e) { + Slog.w(TAG, "Failed parsing config " + e); + } catch (XmlPullParserException e) { + Slog.w(TAG, "Failed parsing config " + e); + } catch (IOException e) { + Slog.w(TAG, "Failed parsing config " + e); + } catch (IndexOutOfBoundsException e) { + Slog.w(TAG, "Failed parsing config " + e); + } + } + + void writeConfigFileLocked() { + mHandler.removeMessages(MSG_WRITE_CONFIG); + mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000); + } + + void handleWriteConfigFile() { + final ByteArrayOutputStream memStream = new ByteArrayOutputStream(); + + try { + synchronized (this) { + XmlSerializer out = new FastXmlSerializer(); + out.setOutput(memStream, "utf-8"); + writeConfigFileLocked(out); + } + } catch (IOException e) { + } + + synchronized (mConfigFile) { + FileOutputStream stream = null; + try { + stream = mConfigFile.startWrite(); + memStream.writeTo(stream); + stream.flush(); + FileUtils.sync(stream); + stream.close(); + mConfigFile.finishWrite(stream); + } catch (IOException e) { + Slog.w(TAG, "Error writing config file", e); + mConfigFile.failWrite(stream); + } + } + } + + void writeConfigFileLocked(XmlSerializer out) throws IOException { + out.startDocument(null, true); + out.startTag(null, "config"); + for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) { + String name = mPowerSaveWhitelistUserApps.keyAt(i); + out.startTag(null, "wl"); + out.attribute(null, "n", name); + out.endTag(null, "wl"); + } + out.endTag(null, "config"); + out.endDocument(); + } + + private void dumpHelp(PrintWriter pw) { + pw.println("Device idle controller (deviceidle) dump options:"); + pw.println(" [-h] [CMD]"); + pw.println(" -h: print this help text."); + pw.println("Commands:"); + pw.println(" step"); + pw.println(" Immediately step to next state, without waiting for alarm."); + pw.println(" whitelist"); + pw.println(" Add (prefix with +) or remove (prefix with -) packages."); + } + + void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump DeviceIdleController from from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + + " without permission " + android.Manifest.permission.DUMP); + return; + } + + if (args != null) { + for (int i=0; i<args.length; i++) { + String arg = args[i]; + if ("-h".equals(arg)) { + dumpHelp(pw); + return; + } else if ("step".equals(arg)) { + synchronized (this) { + stepIdleStateLocked(); + pw.print("Stepped to: "); pw.println(stateToString(mState)); + } + return; + } else if ("whitelist".equals(arg)) { + i++; + while (i < args.length) { + arg = args[i]; + i++; + if (arg.length() < 1 || (arg.charAt(0) != '-' + && arg.charAt(0) != '+')) { + pw.println("Package must be prefixed with + or -: " + arg); + return; + } + char op = arg.charAt(0); + String pkg = arg.substring(1); + if (op == '+') { + if (addPowerSaveWhitelistAppInternal(pkg)) { + pw.println("Added: " + pkg); + } else { + pw.println("Unknown package: " + pkg); + } + } else { + if (removePowerSaveWhitelistAppInternal(pkg)) { + pw.println("Removed: " + pkg); + } + } + } + return; + } else if (arg.length() > 0 && arg.charAt(0) == '-'){ + pw.println("Unknown option: " + arg); + return; + } else { + pw.println("Unknown command: " + arg); + return; + } + } + } + + synchronized (this) { + int size = mPowerSaveWhitelistApps.size(); + if (size > 0) { + pw.println(" Whitelist system apps:"); + for (int i = 0; i < size; i++) { + pw.print(" "); + pw.println(mPowerSaveWhitelistApps.keyAt(i)); + } + } + size = mPowerSaveWhitelistUserApps.size(); + if (size > 0) { + pw.println(" Whitelist user apps:"); + for (int i = 0; i < size; i++) { + pw.print(" "); + pw.println(mPowerSaveWhitelistUserApps.keyAt(i)); + } + } + size = mPowerSaveWhitelistAppIds.size(); + if (size > 0) { + pw.println(" Whitelist app uids:"); + for (int i = 0; i < size; i++) { + pw.print(" UID="); + pw.print(mPowerSaveWhitelistAppIds.keyAt(i)); + pw.print(": "); + pw.print(mPowerSaveWhitelistAppIds.valueAt(i)); + pw.println(); + } + } + pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor); + pw.print(" mCurDisplay="); pw.println(mCurDisplay); + pw.print(" mScreenOn="); pw.println(mScreenOn); + pw.print(" mCharging="); pw.println(mCharging); + pw.print(" mSigMotionActive="); pw.println(mSigMotionActive); + pw.print(" mState="); pw.println(stateToString(mState)); + pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw); + pw.println(); + if (mNextAlarmTime != 0) { + pw.print(" mNextAlarmTime="); + TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw); + pw.println(); + } + if (mNextIdlePendingDelay != 0) { + pw.print(" mNextIdlePendingDelay="); + TimeUtils.formatDuration(mNextIdlePendingDelay, pw); + pw.println(); + } + if (mNextIdleDelay != 0) { + pw.print(" mNextIdleDelay="); + TimeUtils.formatDuration(mNextIdleDelay, pw); + pw.println(); + } + } + } +} diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags index abd2ca04562e..ef9d0c3fa292 100644 --- a/services/core/java/com/android/server/EventLogTags.logtags +++ b/services/core/java/com/android/server/EventLogTags.logtags @@ -180,6 +180,11 @@ option java_package com.android.server 34001 device_idle_step 34002 device_idle_wake_from_idle (is_idle|1|5), (reason|3) +# --------------------------- +# DisplayManagerService.java +# --------------------------- +# Auto-brightness adjustments by the user. +35000 auto_brightness_adj (old_adj|5),(old_lux|5),(old_brightness|5),(old_gamma|5),(new_adj|5),(new_lux|5),(new_brightness|5),(new_gamma|5) # --------------------------- # ConnectivityService.java diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 7172ab78b8b8..74adeb7f5b96 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -62,11 +62,11 @@ import android.os.storage.StorageManager; import android.os.storage.StorageResultCode; import android.os.storage.StorageVolume; import android.os.storage.VolumeInfo; +import android.os.storage.VolumeRecord; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.AtomicFile; -import android.util.DebugUtils; import android.util.Log; import android.util.Slog; import android.util.Xml; @@ -251,49 +251,7 @@ class MountService extends IMountService.Stub private static final String ATTR_NICKNAME = "nickname"; private static final String ATTR_USER_FLAGS = "userFlags"; - private final AtomicFile mMetadataFile; - - private static class VolumeMetadata { - public final int type; - public final String fsUuid; - public String nickname; - public int userFlags; - - public VolumeMetadata(int type, String fsUuid) { - this.type = type; - this.fsUuid = Preconditions.checkNotNull(fsUuid); - } - - public static VolumeMetadata read(XmlPullParser in) throws IOException { - final int type = readIntAttribute(in, ATTR_TYPE); - final String fsUuid = readStringAttribute(in, ATTR_FS_UUID); - final VolumeMetadata meta = new VolumeMetadata(type, fsUuid); - meta.nickname = readStringAttribute(in, ATTR_NICKNAME); - meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS); - return meta; - } - - public static void write(XmlSerializer out, VolumeMetadata meta) throws IOException { - out.startTag(null, TAG_VOLUME); - writeIntAttribute(out, ATTR_TYPE, meta.type); - writeStringAttribute(out, ATTR_FS_UUID, meta.fsUuid); - writeStringAttribute(out, ATTR_NICKNAME, meta.nickname); - writeIntAttribute(out, ATTR_USER_FLAGS, meta.userFlags); - out.endTag(null, TAG_VOLUME); - } - - public void dump(IndentingPrintWriter pw) { - pw.println("VolumeMetadata:"); - pw.increaseIndent(); - pw.printPair("type", DebugUtils.valueToString(VolumeInfo.class, "TYPE_", type)); - pw.printPair("fsUuid", fsUuid); - pw.printPair("nickname", nickname); - pw.printPair("userFlags", - DebugUtils.flagsToString(VolumeInfo.class, "USER_FLAG_", userFlags)); - pw.decreaseIndent(); - pw.println(); - } - } + private final AtomicFile mSettingsFile; /** * <em>Never</em> hold the lock while performing downcalls into vold, since @@ -311,9 +269,9 @@ class MountService extends IMountService.Stub @GuardedBy("mLock") private ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>(); - /** Map from UUID to metadata */ + /** Map from UUID to record */ @GuardedBy("mLock") - private ArrayMap<String, VolumeMetadata> mMetadata = new ArrayMap<>(); + private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>(); @GuardedBy("mLock") private String mPrimaryStorageUuid; @@ -370,15 +328,6 @@ class MountService extends IMountService.Stub } } - private VolumeMetadata findOrCreateMetadataLocked(VolumeInfo vol) { - VolumeMetadata meta = mMetadata.get(vol.fsUuid); - if (meta == null) { - meta = new VolumeMetadata(vol.type, vol.fsUuid); - mMetadata.put(meta.fsUuid, meta); - } - return meta; - } - private CountDownLatch findOrCreateDiskScanLatch(String diskId) { synchronized (mLock) { CountDownLatch latch = mDiskScanLatches.get(diskId); @@ -580,7 +529,9 @@ class MountService extends IMountService.Stub case H_FSTRIM: { if (!isReady()) { Slog.i(TAG, "fstrim requested, but no daemon connection yet; trying again"); - sendMessageDelayed(obtainMessage(H_FSTRIM), DateUtils.SECOND_IN_MILLIS); + sendMessageDelayed(obtainMessage(H_FSTRIM, msg.obj), + DateUtils.SECOND_IN_MILLIS); + break; } Slog.i(TAG, "Running fstrim idle maintenance"); @@ -911,7 +862,7 @@ class MountService extends IMountService.Stub final int oldState = vol.state; final int newState = Integer.parseInt(cooked[2]); vol.state = newState; - onVolumeStateChangedLocked(vol.clone(), oldState, newState); + onVolumeStateChangedLocked(vol, oldState, newState); } break; } @@ -921,7 +872,6 @@ class MountService extends IMountService.Stub if (vol != null) { vol.fsType = cooked[2]; } - mCallbacks.notifyVolumeMetadataChanged(vol.clone()); break; } case VoldResponseCode.VOLUME_FS_UUID_CHANGED: { @@ -930,8 +880,6 @@ class MountService extends IMountService.Stub if (vol != null) { vol.fsUuid = cooked[2]; } - refreshMetadataLocked(); - mCallbacks.notifyVolumeMetadataChanged(vol.clone()); break; } case VoldResponseCode.VOLUME_FS_LABEL_CHANGED: { @@ -943,7 +891,7 @@ class MountService extends IMountService.Stub } vol.fsLabel = builder.toString().trim(); } - mCallbacks.notifyVolumeMetadataChanged(vol.clone()); + // TODO: notify listeners that label changed break; } case VoldResponseCode.VOLUME_PATH_CHANGED: { @@ -1068,6 +1016,19 @@ class MountService extends IMountService.Stub } private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) { + // Remember that we saw this volume so we're ready to accept user + // metadata, or so we can annoy them when a private volume is ejected + if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) { + if (!mRecords.containsKey(vol.fsUuid)) { + final VolumeRecord rec = new VolumeRecord(vol.type, vol.fsUuid); + if (vol.type == VolumeInfo.TYPE_PRIVATE) { + rec.nickname = vol.disk.getDescription(); + } + mRecords.put(rec.fsUuid, rec); + writeSettingsLocked(); + } + } + mCallbacks.notifyVolumeStateChanged(vol, oldState, newState); if (isBroadcastWorthy(vol)) { @@ -1115,7 +1076,7 @@ class MountService extends IMountService.Stub // TODO: estimate remaining time try { - mMoveCallback.onStatusChanged(-1, status, -1); + mMoveCallback.onStatusChanged(-1, null, status, -1); } catch (RemoteException ignored) { } @@ -1125,7 +1086,7 @@ class MountService extends IMountService.Stub Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting"); mPrimaryStorageUuid = mMoveTargetUuid; - writeMetadataLocked(); + writeSettingsLocked(); } if (PackageManager.isMoveStatusFinished(status)) { @@ -1136,25 +1097,6 @@ class MountService extends IMountService.Stub } } - /** - * Refresh latest metadata into any currently active {@link VolumeInfo}. - */ - private void refreshMetadataLocked() { - final int size = mVolumes.size(); - for (int i = 0; i < size; i++) { - final VolumeInfo vol = mVolumes.valueAt(i); - final VolumeMetadata meta = mMetadata.get(vol.fsUuid); - - if (meta != null) { - vol.nickname = meta.nickname; - vol.userFlags = meta.userFlags; - } else { - vol.nickname = null; - vol.userFlags = 0; - } - } - } - private void enforcePermission(String perm) { mContext.enforceCallingOrSelfPermission(perm, perm); } @@ -1203,11 +1145,11 @@ class MountService extends IMountService.Stub mLastMaintenance = mLastMaintenanceFile.lastModified(); } - mMetadataFile = new AtomicFile( + mSettingsFile = new AtomicFile( new File(Environment.getSystemSecureDirectory(), "storage.xml")); synchronized (mLock) { - readMetadataLocked(); + readSettingsLocked(); } /* @@ -1233,12 +1175,12 @@ class MountService extends IMountService.Stub mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget(); } - private void readMetadataLocked() { - mMetadata.clear(); + private void readSettingsLocked() { + mRecords.clear(); FileInputStream fis = null; try { - fis = mMetadataFile.openRead(); + fis = mSettingsFile.openRead(); final XmlPullParser in = Xml.newPullParser(); in.setInput(fis, null); @@ -1261,8 +1203,8 @@ class MountService extends IMountService.Stub } } else if (TAG_VOLUME.equals(tag)) { - final VolumeMetadata meta = VolumeMetadata.read(in); - mMetadata.put(meta.fsUuid, meta); + final VolumeRecord rec = readVolumeRecord(in); + mRecords.put(rec.fsUuid, rec); } } } @@ -1277,10 +1219,10 @@ class MountService extends IMountService.Stub } } - private void writeMetadataLocked() { + private void writeSettingsLocked() { FileOutputStream fos = null; try { - fos = mMetadataFile.startWrite(); + fos = mSettingsFile.startWrite(); XmlSerializer out = new FastXmlSerializer(); out.setOutput(fos, "utf-8"); @@ -1288,22 +1230,40 @@ class MountService extends IMountService.Stub out.startTag(null, TAG_VOLUMES); writeIntAttribute(out, ATTR_VERSION, VERSION_ADD_PRIMARY); writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid); - final int size = mMetadata.size(); + final int size = mRecords.size(); for (int i = 0; i < size; i++) { - final VolumeMetadata meta = mMetadata.valueAt(i); - VolumeMetadata.write(out, meta); + final VolumeRecord rec = mRecords.valueAt(i); + writeVolumeRecord(out, rec); } out.endTag(null, TAG_VOLUMES); out.endDocument(); - mMetadataFile.finishWrite(fos); + mSettingsFile.finishWrite(fos); } catch (IOException e) { if (fos != null) { - mMetadataFile.failWrite(fos); + mSettingsFile.failWrite(fos); } } } + public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException { + final int type = readIntAttribute(in, ATTR_TYPE); + final String fsUuid = readStringAttribute(in, ATTR_FS_UUID); + final VolumeRecord meta = new VolumeRecord(type, fsUuid); + meta.nickname = readStringAttribute(in, ATTR_NICKNAME); + meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS); + return meta; + } + + public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException { + out.startTag(null, TAG_VOLUME); + writeIntAttribute(out, ATTR_TYPE, rec.type); + writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid); + writeStringAttribute(out, ATTR_NICKNAME, rec.nickname); + writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags); + out.endTag(null, TAG_VOLUME); + } + /** * Exposed API calls below here */ @@ -1469,32 +1429,40 @@ class MountService extends IMountService.Stub } @Override - public void setVolumeNickname(String volId, String nickname) { + public void setVolumeNickname(String fsUuid, String nickname) { + enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); + waitForReady(); + + synchronized (mLock) { + final VolumeRecord rec = mRecords.get(fsUuid); + rec.nickname = nickname; + mCallbacks.notifyVolumeMetadataChanged(fsUuid); + writeSettingsLocked(); + } + } + + @Override + public void setVolumeUserFlags(String fsUuid, int flags, int mask) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); waitForReady(); synchronized (mLock) { - final VolumeInfo vol = findVolumeById(volId); - final VolumeMetadata meta = findOrCreateMetadataLocked(vol); - meta.nickname = nickname; - refreshMetadataLocked(); - writeMetadataLocked(); - mCallbacks.notifyVolumeMetadataChanged(vol.clone()); + final VolumeRecord rec = mRecords.get(fsUuid); + rec.userFlags = (rec.userFlags & ~mask) | (flags & mask); + mCallbacks.notifyVolumeMetadataChanged(fsUuid); + writeSettingsLocked(); } } @Override - public void setVolumeUserFlags(String volId, int flags, int mask) { + public void forgetVolume(String fsUuid) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); waitForReady(); synchronized (mLock) { - final VolumeInfo vol = findVolumeById(volId); - final VolumeMetadata meta = findOrCreateMetadataLocked(vol); - meta.userFlags = (meta.userFlags & ~mask) | (flags & mask); - refreshMetadataLocked(); - writeMetadataLocked(); - mCallbacks.notifyVolumeMetadataChanged(vol.clone()); + mRecords.remove(fsUuid); + mCallbacks.notifyVolumeMetadataChanged(fsUuid); + writeSettingsLocked(); } } @@ -2327,11 +2295,6 @@ class MountService extends IMountService.Stub @Override public VolumeInfo[] getVolumes(int flags) { - if ((flags & StorageManager.FLAG_ALL_METADATA) != 0) { - // TODO: implement support for returning all metadata - throw new UnsupportedOperationException(); - } - synchronized (mLock) { final VolumeInfo[] res = new VolumeInfo[mVolumes.size()]; for (int i = 0; i < mVolumes.size(); i++) { @@ -2341,6 +2304,17 @@ class MountService extends IMountService.Stub } } + @Override + public VolumeRecord[] getVolumeRecords(int flags) { + synchronized (mLock) { + final VolumeRecord[] res = new VolumeRecord[mRecords.size()]; + for (int i = 0; i < mRecords.size(); i++) { + res[i] = mRecords.valueAt(i); + } + return res; + } + } + private void addObbStateLocked(ObbState obbState) throws RemoteException { final IBinder binder = obbState.getBinder(); List<ObbState> obbStates = mObbMounts.get(binder); @@ -2890,7 +2864,7 @@ class MountService extends IMountService.Stub break; } case MSG_VOLUME_METADATA_CHANGED: { - callback.onVolumeMetadataChanged((VolumeInfo) args.arg1); + callback.onVolumeMetadataChanged((String) args.arg1); break; } case MSG_DISK_SCANNED: { @@ -2910,21 +2884,21 @@ class MountService extends IMountService.Stub private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) { final SomeArgs args = SomeArgs.obtain(); - args.arg1 = vol; + args.arg1 = vol.clone(); args.argi2 = oldState; args.argi3 = newState; obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget(); } - private void notifyVolumeMetadataChanged(VolumeInfo vol) { + private void notifyVolumeMetadataChanged(String fsUuid) { final SomeArgs args = SomeArgs.obtain(); - args.arg1 = vol; + args.arg1 = fsUuid; obtainMessage(MSG_VOLUME_METADATA_CHANGED, args).sendToTarget(); } private void notifyDiskScanned(DiskInfo disk, int volumeCount) { final SomeArgs args = SomeArgs.obtain(); - args.arg1 = disk; + args.arg1 = disk.clone(); args.argi2 = volumeCount; obtainMessage(MSG_DISK_SCANNED, args).sendToTarget(); } @@ -2935,10 +2909,10 @@ class MountService extends IMountService.Stub mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); for (String arg : args) { - if ("--clear-metadata".equals(arg)) { + if ("--clear".equals(arg)) { synchronized (mLock) { - mMetadata.clear(); - writeMetadataLocked(); + mRecords.clear(); + writeSettingsLocked(); } } } @@ -2964,11 +2938,11 @@ class MountService extends IMountService.Stub pw.decreaseIndent(); pw.println(); - pw.println("Metadata:"); + pw.println("Records:"); pw.increaseIndent(); - for (int i = 0; i < mMetadata.size(); i++) { - final VolumeMetadata meta = mMetadata.valueAt(i); - meta.dump(pw); + for (int i = 0; i < mRecords.size(); i++) { + final VolumeRecord note = mRecords.valueAt(i); + note.dump(pw); } pw.decreaseIndent(); diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 999e91bb9714..ac2f5b0db588 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -54,6 +54,7 @@ import android.database.Cursor; import android.database.DatabaseUtils; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; +import android.database.sqlite.SQLiteStatement; import android.os.Binder; import android.os.Bundle; import android.os.Environment; @@ -83,9 +84,12 @@ import com.google.android.collect.Sets; import java.io.File; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; @@ -109,7 +113,9 @@ public class AccountManagerService private static final int TIMEOUT_DELAY_MS = 1000 * 60; private static final String DATABASE_NAME = "accounts.db"; - private static final int DATABASE_VERSION = 7; + private static final int DATABASE_VERSION = 8; + + private static final int MAX_DEBUG_DB_SIZE = 64; private final Context mContext; @@ -214,6 +220,9 @@ public class AccountManagerService private final HashMap<Account, AtomicReference<String>> previousNameCache = new HashMap<Account, AtomicReference<String>>(); + private int debugDbInsertionPoint = -1; + private SQLiteStatement statementForLogging; + UserAccounts(Context context, int userId) { this.userId = userId; synchronized (cacheLock) { @@ -320,6 +329,8 @@ public class AccountManagerService UserAccounts accounts = mUsers.get(userId); if (accounts == null) { accounts = new UserAccounts(mContext, userId); + initializeDebugDbSizeAndCompileSqlStatementForLogging( + accounts.openHelper.getWritableDatabase(), accounts); mUsers.append(userId, accounts); purgeOldGrants(accounts); validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */); @@ -407,6 +418,10 @@ public class AccountManagerService + accountType + " no longer has a registered authenticator"); db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null); accountDeleted = true; + + logRecord(db, DebugDbHelper.ACTION_AUTHENTICATOR_REMOVE, TABLE_ACCOUNTS, + accountId, accounts); + final Account account = new Account(accountName, accountType); accounts.userDataCache.remove(account); accounts.authTokenCache.remove(account); @@ -666,9 +681,10 @@ public class AccountManagerService UserAccounts accounts = getUserAccountsForCaller(); // fails if the account already exists + int uid = getCallingUid(); long identityToken = clearCallingIdentity(); try { - return addAccountInternal(accounts, account, password, extras, false); + return addAccountInternal(accounts, account, password, extras, false, uid); } finally { restoreCallingIdentity(identityToken); } @@ -811,7 +827,7 @@ public class AccountManagerService } private boolean addAccountInternal(UserAccounts accounts, Account account, String password, - Bundle extras, boolean restricted) { + Bundle extras, boolean restricted, int callingUid) { if (account == null) { return false; } @@ -850,6 +866,10 @@ public class AccountManagerService } } db.setTransactionSuccessful(); + + logRecord(db, DebugDbHelper.ACTION_ACCOUNT_ADD, TABLE_ACCOUNTS, accountId, + accounts, callingUid); + insertAccountIntoCacheLocked(accounts, account); } finally { db.endTransaction(); @@ -983,9 +1003,12 @@ public class AccountManagerService if (accountToRename == null) throw new IllegalArgumentException("account is null"); checkAuthenticateAccountsPermission(accountToRename); UserAccounts accounts = getUserAccountsForCaller(); + + int callingUid = getCallingUid(); long identityToken = clearCallingIdentity(); try { - Account resultingAccount = renameAccountInternal(accounts, accountToRename, newName); + Account resultingAccount = renameAccountInternal(accounts, accountToRename, newName, + callingUid); Bundle result = new Bundle(); result.putString(AccountManager.KEY_ACCOUNT_NAME, resultingAccount.name); result.putString(AccountManager.KEY_ACCOUNT_TYPE, resultingAccount.type); @@ -1000,7 +1023,7 @@ public class AccountManagerService } private Account renameAccountInternal( - UserAccounts accounts, Account accountToRename, String newName) { + UserAccounts accounts, Account accountToRename, String newName, int callingUid) { Account resultAccount = null; /* * Cancel existing notifications. Let authenticators @@ -1038,6 +1061,8 @@ public class AccountManagerService db.update(TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId); db.setTransactionSuccessful(); isSuccessful = true; + logRecord(db, DebugDbHelper.ACTION_ACCOUNT_RENAME, TABLE_ACCOUNTS, accountId, + accounts); } } finally { db.endTransaction(); @@ -1131,6 +1156,8 @@ public class AccountManagerService } } + logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_REMOVE, TABLE_ACCOUNTS); + try { new RemoveAccountSession(accounts, response, account, expectActivityLaunch).bind(); } finally { @@ -1188,6 +1215,8 @@ public class AccountManagerService } } + logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_REMOVE, TABLE_ACCOUNTS); + try { new RemoveAccountSession(accounts, response, account, expectActivityLaunch).bind(); } finally { @@ -1210,6 +1239,9 @@ public class AccountManagerService if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) { return false; } + + logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_REMOVE, TABLE_ACCOUNTS); + long identityToken = clearCallingIdentity(); try { return removeAccountInternal(accounts, account); @@ -1275,21 +1307,25 @@ public class AccountManagerService int deleted; synchronized (accounts.cacheLock) { final SQLiteDatabase db = accounts.openHelper.getWritableDatabase(); + final long accountId = getAccountIdLocked(db, account); deleted = db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?", new String[]{account.name, account.type}); removeAccountFromCacheLocked(accounts, account); sendAccountsChangedBroadcast(accounts.userId); + + logRecord(db, DebugDbHelper.ACTION_ACCOUNT_REMOVE, TABLE_ACCOUNTS, accountId, accounts); } if (accounts.userId == UserHandle.USER_OWNER) { // Owner's account was removed, remove from any users that are sharing // this account. + int callingUid = getCallingUid(); long id = Binder.clearCallingIdentity(); try { List<UserInfo> users = mUserManager.getUsers(true); for (UserInfo user : users) { if (!user.isPrimary() && user.isRestricted()) { - removeSharedAccountAsUser(account, user.id); + removeSharedAccountAsUser(account, user.id, callingUid); } } } finally { @@ -1441,15 +1477,17 @@ public class AccountManagerService if (account == null) throw new IllegalArgumentException("account is null"); checkAuthenticateAccountsPermission(account); UserAccounts accounts = getUserAccountsForCaller(); + int callingUid = getCallingUid(); long identityToken = clearCallingIdentity(); try { - setPasswordInternal(accounts, account, password); + setPasswordInternal(accounts, account, password, callingUid); } finally { restoreCallingIdentity(identityToken); } } - private void setPasswordInternal(UserAccounts accounts, Account account, String password) { + private void setPasswordInternal(UserAccounts accounts, Account account, String password, + int callingUid) { if (account == null) { return; } @@ -1473,6 +1511,11 @@ public class AccountManagerService db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?", argsAccountId); accounts.authTokenCache.remove(account); db.setTransactionSuccessful(); + + String action = (password == null || password.length() == 0) ? + DebugDbHelper.ACTION_CLEAR_PASSWORD + : DebugDbHelper.ACTION_SET_PASSWORD; + logRecord(db, action, TABLE_ACCOUNTS, accountId, accounts, callingUid); } } finally { db.endTransaction(); @@ -1497,9 +1540,11 @@ public class AccountManagerService if (account == null) throw new IllegalArgumentException("account is null"); checkManageAccountsPermission(); UserAccounts accounts = getUserAccountsForCaller(); + + int callingUid = getCallingUid(); long identityToken = clearCallingIdentity(); try { - setPasswordInternal(accounts, account, null); + setPasswordInternal(accounts, account, null, callingUid); } finally { restoreCallingIdentity(identityToken); } @@ -1888,6 +1933,8 @@ public class AccountManagerService options.putInt(AccountManager.KEY_CALLER_UID, uid); options.putInt(AccountManager.KEY_CALLER_PID, pid); + logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_ADD, TABLE_ACCOUNTS); + long identityToken = clearCallingIdentity(); try { new Session(accounts, response, accountType, expectActivityLaunch, @@ -1964,6 +2011,8 @@ public class AccountManagerService options.putInt(AccountManager.KEY_CALLER_UID, uid); options.putInt(AccountManager.KEY_CALLER_PID, pid); + logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_ADD, TABLE_ACCOUNTS); + long identityToken = clearCallingIdentity(); try { new Session(accounts, response, accountType, expectActivityLaunch, @@ -2320,7 +2369,8 @@ public class AccountManagerService @Override public boolean addSharedAccountAsUser(Account account, int userId) { userId = handleIncomingUser(userId); - SQLiteDatabase db = getUserAccounts(userId).openHelper.getWritableDatabase(); + UserAccounts accounts = getUserAccounts(userId); + SQLiteDatabase db = accounts.openHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(ACCOUNTS_NAME, account.name); values.put(ACCOUNTS_TYPE, account.type); @@ -2332,6 +2382,7 @@ public class AccountManagerService + ", skipping the DB insert failed"); return false; } + logRecord(db, DebugDbHelper.ACTION_ACCOUNT_ADD, TABLE_SHARED_ACCOUNTS, accountId, accounts); return true; } @@ -2340,6 +2391,7 @@ public class AccountManagerService userId = handleIncomingUser(userId); UserAccounts accounts = getUserAccounts(userId); SQLiteDatabase db = accounts.openHelper.getWritableDatabase(); + long sharedTableAccountId = getAccountIdFromSharedTable(db, account); final ContentValues values = new ContentValues(); values.put(ACCOUNTS_NAME, newName); values.put(ACCOUNTS_PREVIOUS_NAME, account.name); @@ -2349,20 +2401,30 @@ public class AccountManagerService ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?", new String[] { account.name, account.type }); if (r > 0) { + int callingUid = getCallingUid(); + logRecord(db, DebugDbHelper.ACTION_ACCOUNT_RENAME, TABLE_SHARED_ACCOUNTS, + sharedTableAccountId, accounts, callingUid); // Recursively rename the account. - renameAccountInternal(accounts, account, newName); + renameAccountInternal(accounts, account, newName, callingUid); } return r > 0; } @Override public boolean removeSharedAccountAsUser(Account account, int userId) { + return removeSharedAccountAsUser(account, userId, getCallingUid()); + } + + private boolean removeSharedAccountAsUser(Account account, int userId, int callingUid) { userId = handleIncomingUser(userId); UserAccounts accounts = getUserAccounts(userId); SQLiteDatabase db = accounts.openHelper.getWritableDatabase(); + long sharedTableAccountId = getAccountIdFromSharedTable(db, account); int r = db.delete(TABLE_SHARED_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?", new String[] {account.name, account.type}); if (r > 0) { + logRecord(db, DebugDbHelper.ACTION_ACCOUNT_REMOVE, TABLE_SHARED_ACCOUNTS, + sharedTableAccountId, accounts, callingUid); removeAccountInternal(accounts, account); } return r > 0; @@ -2459,6 +2521,19 @@ public class AccountManagerService } } + private long getAccountIdFromSharedTable(SQLiteDatabase db, Account account) { + Cursor cursor = db.query(TABLE_SHARED_ACCOUNTS, new String[]{ACCOUNTS_ID}, + "name=? AND type=?", new String[]{account.name, account.type}, null, null, null); + try { + if (cursor.moveToNext()) { + return cursor.getLong(0); + } + return -1; + } finally { + cursor.close(); + } + } + private long getAccountIdLocked(SQLiteDatabase db, Account account) { Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_ID}, "name=? AND type=?", new String[]{account.name, account.type}, null, null, null); @@ -2904,6 +2979,130 @@ public class AccountManagerService return databaseFile.getPath(); } + private static class DebugDbHelper{ + private DebugDbHelper() { + } + + private static String TABLE_DEBUG = "debug_table"; + + // Columns for the table + private static String ACTION_TYPE = "action_type"; + private static String TIMESTAMP = "time"; + private static String CALLER_UID = "caller_uid"; + private static String TABLE_NAME = "table_name"; + private static String KEY = "primary_key"; + + // These actions correspond to the occurrence of real actions. Since + // these are called by the authenticators, the uid associated will be + // of the authenticator. + private static String ACTION_SET_PASSWORD = "action_set_password"; + private static String ACTION_CLEAR_PASSWORD = "action_clear_password"; + private static String ACTION_ACCOUNT_ADD = "action_account_add"; + private static String ACTION_ACCOUNT_REMOVE = "action_account_remove"; + private static String ACTION_AUTHENTICATOR_REMOVE = "action_authenticator_remove"; + private static String ACTION_ACCOUNT_RENAME = "action_account_rename"; + + // These actions don't necessarily correspond to any action on + // accountDb taking place. As an example, there might be a request for + // addingAccount, which might not lead to addition of account on grounds + // of bad authentication. We will still be logging it to keep track of + // who called. + private static String ACTION_CALLED_ACCOUNT_ADD = "action_called_account_add"; + private static String ACTION_CALLED_ACCOUNT_REMOVE = "action_called_account_remove"; + private static String ACTION_CALLED_ACCOUNT_RENAME = "action_called_account_rename"; + + private static SimpleDateFormat dateFromat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + private static String UPDATE_WHERE_CLAUSE = KEY + "=?"; + + private static void createDebugTable(SQLiteDatabase db) { + db.execSQL("CREATE TABLE " + TABLE_DEBUG + " ( " + + ACCOUNTS_ID + " INTEGER," + + ACTION_TYPE + " TEXT NOT NULL, " + + TIMESTAMP + " DATETIME," + + CALLER_UID + " INTEGER NOT NULL," + + TABLE_NAME + " TEXT NOT NULL," + + KEY + " INTEGER PRIMARY KEY)"); + db.execSQL("CREATE INDEX timestamp_index ON " + TABLE_DEBUG + " (" + TIMESTAMP + ")"); + } + } + + private void logRecord(UserAccounts accounts, String action, String tableName) { + SQLiteDatabase db = accounts.openHelper.getWritableDatabase(); + logRecord(db, action, tableName, -1, accounts); + } + + /* + * This function receives an opened writable database. + */ + private void logRecord(SQLiteDatabase db, String action, String tableName, long accountId, + UserAccounts userAccount) { + logRecord(db, action, tableName, accountId, userAccount, getCallingUid()); + } + + /* + * This function receives an opened writable database. + */ + private void logRecord(SQLiteDatabase db, String action, String tableName, long accountId, + UserAccounts userAccount, int callingUid) { + SQLiteStatement logStatement = userAccount.statementForLogging; + logStatement.bindLong(1, accountId); + logStatement.bindString(2, action); + logStatement.bindString(3, DebugDbHelper.dateFromat.format(new Date())); + logStatement.bindLong(4, callingUid); + logStatement.bindString(5, tableName); + logStatement.bindLong(6, userAccount.debugDbInsertionPoint); + logStatement.execute(); + logStatement.clearBindings(); + userAccount.debugDbInsertionPoint = (userAccount.debugDbInsertionPoint + 1) + % MAX_DEBUG_DB_SIZE; + } + + /* + * This should only be called once to compile the sql statement for logging + * and to find the insertion point. + */ + private void initializeDebugDbSizeAndCompileSqlStatementForLogging(SQLiteDatabase db, + UserAccounts userAccount) { + // Initialize the count if not done earlier. + int size = (int) getDebugTableRowCount(db); + if (size >= MAX_DEBUG_DB_SIZE) { + // Table is full, and we need to find the point where to insert. + userAccount.debugDbInsertionPoint = (int) getDebugTableInsertionPoint(db); + } else { + userAccount.debugDbInsertionPoint = size; + } + compileSqlStatementForLogging(db, userAccount); + } + + private void compileSqlStatementForLogging(SQLiteDatabase db, UserAccounts userAccount) { + String sql = "INSERT OR REPLACE INTO " + DebugDbHelper.TABLE_DEBUG + + " VALUES (?,?,?,?,?,?)"; + userAccount.statementForLogging = db.compileStatement(sql); + } + + private long getDebugTableRowCount(SQLiteDatabase db) { + String queryCountDebugDbRows = "SELECT COUNT(*) FROM " + DebugDbHelper.TABLE_DEBUG; + return DatabaseUtils.longForQuery(db, queryCountDebugDbRows, null); + } + + /* + * Finds the row key where the next insertion should take place. This should + * be invoked only if the table has reached its full capacity. + */ + private long getDebugTableInsertionPoint(SQLiteDatabase db) { + // This query finds the smallest timestamp value (and if 2 records have + // same timestamp, the choose the lower id). + String queryCountDebugDbRows = new StringBuilder() + .append("SELECT ").append(DebugDbHelper.KEY) + .append(" FROM ").append(DebugDbHelper.TABLE_DEBUG) + .append(" ORDER BY ") + .append(DebugDbHelper.TIMESTAMP).append(",").append(DebugDbHelper.KEY) + .append(" LIMIT 1") + .toString(); + return DatabaseUtils.longForQuery(db, queryCountDebugDbRows, null); + } + static class DatabaseHelper extends SQLiteOpenHelper { public DatabaseHelper(Context context, int userId) { @@ -2949,6 +3148,8 @@ public class AccountManagerService createSharedAccountsTable(db); createAccountsDeletionTrigger(db); + + DebugDbHelper.createDebugTable(db); } private void createSharedAccountsTable(SQLiteDatabase db) { @@ -2968,6 +3169,10 @@ public class AccountManagerService db.execSQL("ALTER TABLE " + TABLE_ACCOUNTS + " ADD COLUMN " + ACCOUNTS_PREVIOUS_NAME); } + private void addDebugTable(SQLiteDatabase db) { + DebugDbHelper.createDebugTable(db); + } + private void createAccountsDeletionTrigger(SQLiteDatabase db) { db.execSQL("" + " CREATE TRIGGER " + TABLE_ACCOUNTS + "Delete DELETE ON " + TABLE_ACCOUNTS @@ -3028,6 +3233,11 @@ public class AccountManagerService oldVersion++; } + if (oldVersion == 7) { + addDebugTable(db); + oldVersion++; + } + if (oldVersion != newVersion) { Log.e(TAG, "failed to upgrade version " + oldVersion + " to version " + newVersion); } @@ -3109,6 +3319,23 @@ public class AccountManagerService fout.println(" " + account); } + // Add debug information. + fout.println(); + Cursor cursor = db.query(DebugDbHelper.TABLE_DEBUG, null, + null, null, null, null, DebugDbHelper.TIMESTAMP); + fout.println("AccountId, Action_Type, timestamp, UID, TableName, Key"); + fout.println("Accounts History"); + try { + while (cursor.moveToNext()) { + // print type,count + fout.println(cursor.getString(0) + "," + cursor.getString(1) + "," + + cursor.getString(2) + "," + cursor.getString(3) + "," + + cursor.getString(4) + "," + cursor.getString(5)); + } + } finally { + cursor.close(); + } + fout.println(); synchronized (mSessions) { final long now = SystemClock.elapsedRealtime(); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 15d736776812..25a98c00a128 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -699,12 +699,10 @@ public final class ActivityManagerService extends ActivityManagerNative private final StringBuilder mStrictModeBuffer = new StringBuilder(); /** - * Keeps track of all IIntentReceivers that have been registered for - * broadcasts. Hash keys are the receiver IBinder, hash value is - * a ReceiverList. + * Keeps track of all IIntentReceivers that have been registered for broadcasts. + * Hash keys are the receiver IBinder, hash value is a ReceiverList. */ - final HashMap<IBinder, ReceiverList> mRegisteredReceivers = - new HashMap<IBinder, ReceiverList>(); + final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>(); /** * Resolver for broadcast intents to registered receivers. @@ -716,7 +714,7 @@ public final class ActivityManagerService extends ActivityManagerNative protected boolean allowFilterResult( BroadcastFilter filter, List<BroadcastFilter> dest) { IBinder target = filter.receiverList.receiver.asBinder(); - for (int i=dest.size()-1; i>=0; i--) { + for (int i = dest.size() - 1; i >= 0; i--) { if (dest.get(i).receiverList.receiver.asBinder() == target) { return false; } @@ -6603,6 +6601,12 @@ public final class ActivityManagerService extends ActivityManagerNative return mActivityManagerService.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_GRANTED; } + + @Override + public String[] getPackagesForUid(int uid) { + return mActivityManagerService.mContext.getPackageManager() + .getPackagesForUid(uid); + } } class IntentFirewallInterface implements IntentFirewall.AMSInterface { @@ -15656,8 +15660,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Original caller already died return null; } - ReceiverList rl - = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder()); + ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); if (rl == null) { rl = new ReceiverList(this, callerApp, callingPid, callingUid, userId, receiver); @@ -15689,7 +15692,7 @@ public final class ActivityManagerService extends ActivityManagerNative permission, callingUid, userId); rl.add(bf); if (!bf.debugCheck()) { - Slog.w(TAG, "==> For Dynamic broadast"); + Slog.w(TAG, "==> For Dynamic broadcast"); } mReceiverResolver.addFilter(bf); @@ -15699,9 +15702,9 @@ public final class ActivityManagerService extends ActivityManagerNative ArrayList receivers = new ArrayList(); receivers.add(bf); - int N = allSticky.size(); - for (int i=0; i<N; i++) { - Intent intent = (Intent)allSticky.get(i); + final int stickyCount = allSticky.size(); + for (int i = 0; i < stickyCount; i++) { + Intent intent = allSticky.get(i); BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, null, null, -1, -1, null, null, AppOpsManager.OP_NONE, receivers, null, 0, @@ -15761,8 +15764,7 @@ public final class ActivityManagerService extends ActivityManagerNative void removeReceiverLocked(ReceiverList rl) { mRegisteredReceivers.remove(rl.receiver.asBinder()); - int N = rl.size(); - for (int i=0; i<N; i++) { + for (int i = rl.size() - 1; i >= 0; i--) { mReceiverResolver.removeFilter(rl.get(i)); } } @@ -16133,24 +16135,24 @@ public final class ActivityManagerService extends ActivityManagerNative } ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId); if (stickies == null) { - stickies = new ArrayMap<String, ArrayList<Intent>>(); + stickies = new ArrayMap<>(); mStickyBroadcasts.put(userId, stickies); } ArrayList<Intent> list = stickies.get(intent.getAction()); if (list == null) { - list = new ArrayList<Intent>(); + list = new ArrayList<>(); stickies.put(intent.getAction(), list); } - int N = list.size(); + final int stickiesCount = list.size(); int i; - for (i=0; i<N; i++) { + for (i = 0; i < stickiesCount; i++) { if (intent.filterEquals(list.get(i))) { // This sticky already exists, replace it. list.set(i, new Intent(intent)); break; } } - if (i >= N) { + if (i >= stickiesCount) { list.add(new Intent(intent)); } } diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index a91a7ca2f055..e5c5dffdf31c 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -309,7 +309,6 @@ public final class BroadcastQueue { } public void skipCurrentReceiverLocked(ProcessRecord app) { - boolean reschedule = false; BroadcastRecord r = app.curReceiver; if (r != null && r.queue == this) { // The current broadcast is waiting for this app's receiver @@ -318,7 +317,6 @@ public final class BroadcastQueue { logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false); - reschedule = true; } if (r == null && mPendingBroadcast != null && mPendingBroadcast.curApp == app) { if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 6b56279354ba..eb28ed0772be 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -1803,9 +1803,7 @@ public class AudioService extends IAudioService.Stub { if (!shouldMute) { // unmute // ring and notifications volume should never be 0 when not silenced - // on voice capable devices or devices that support vibration - if ((isPlatformVoice() || mHasVibrator) && - mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) { + if (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) { synchronized (VolumeStreamState.class) { final VolumeStreamState vss = mStreamStates[streamType]; for (int i = 0; i < vss.mIndexMap.size(); i++) { @@ -2986,10 +2984,7 @@ public class AudioService extends IAudioService.Stub { mLoweredFromNormalToVibrateTime = SystemClock.uptimeMillis(); } } else { - // (oldIndex < step) is equivalent to (old UI index == 0) - if ((oldIndex < step) - && mVolumePolicy.volumeDownToEnterSilent - && mPrevVolDirection != AudioManager.ADJUST_LOWER) { + if (oldIndex == step && mVolumePolicy.volumeDownToEnterSilent) { ringerMode = RINGER_MODE_SILENT; } } @@ -3018,7 +3013,8 @@ public class AudioService extends IAudioService.Stub { if (mVolumePolicy.volumeDownToEnterSilent) { final long diff = SystemClock.uptimeMillis() - mLoweredFromNormalToVibrateTime; - if (diff > mVolumePolicy.vibrateToSilentDebounce) { + if (diff > mVolumePolicy.vibrateToSilentDebounce + && mRingerModeDelegate.canVolumeDownEnterSilent()) { ringerMode = RINGER_MODE_SILENT; } } else { diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 93d37f1da650..e15bca6ca7a1 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -16,6 +16,7 @@ package com.android.server.display; +import com.android.server.EventLogTags; import com.android.server.LocalServices; import com.android.server.twilight.TwilightListener; import com.android.server.twilight.TwilightManager; @@ -31,13 +32,13 @@ import android.os.Message; import android.os.PowerManager; import android.os.SystemClock; import android.text.format.DateUtils; +import android.util.EventLog; import android.util.MathUtils; import android.util.Spline; import android.util.Slog; import android.util.TimeUtils; import java.io.PrintWriter; -import java.util.Arrays; class AutomaticBrightnessController { private static final String TAG = "AutomaticBrightnessController"; @@ -87,7 +88,12 @@ class AutomaticBrightnessController { // well after dusk. private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 2; + // Debounce for sampling user-initiated changes in display brightness to ensure + // the user is satisfied with the result before storing the sample. + private static final int BRIGHTNESS_ADJUSTMENT_SAMPLE_DEBOUNCE_MILLIS = 10000; + private static final int MSG_UPDATE_AMBIENT_LUX = 1; + private static final int MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE = 2; // Callbacks for requesting updates to the the display's power state private final Callbacks mCallbacks; @@ -179,6 +185,14 @@ class AutomaticBrightnessController { // Are we going to adjust brightness while dozing. private boolean mDozing; + // True if we are collecting a brightness adjustment sample, along with some data + // for the initial state of the sample. + private boolean mBrightnessAdjustmentSamplePending; + private float mBrightnessAdjustmentSampleOldAdjustment; + private float mBrightnessAdjustmentSampleOldLux; + private int mBrightnessAdjustmentSampleOldBrightness; + private float mBrightnessAdjustmentSampleOldGamma; + public AutomaticBrightnessController(Callbacks callbacks, Looper looper, SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime, int brightnessMin, int brightnessMax, float dozeScaleFactor, @@ -216,7 +230,8 @@ class AutomaticBrightnessController { return mScreenAutoBrightness; } - public void configure(boolean enable, float adjustment, boolean dozing) { + public void configure(boolean enable, float adjustment, boolean dozing, + boolean userInitiatedChange) { // While dozing, the application processor may be suspended which will prevent us from // receiving new information from the light sensor. On some devices, we may be able to // switch to a wake-up light sensor instead but for now we will simply disable the sensor @@ -228,6 +243,9 @@ class AutomaticBrightnessController { if (changed) { updateAutoBrightness(false /*sendUpdate*/); } + if (enable && !dozing && userInitiatedChange) { + prepareBrightnessAdjustmentSample(); + } } public void dump(PrintWriter pw) { @@ -486,7 +504,7 @@ class AutomaticBrightnessController { } int newScreenAutoBrightness = - clampScreenBrightness(Math.round(value * PowerManager.BRIGHTNESS_ON)); + clampScreenBrightness(Math.round(value * PowerManager.BRIGHTNESS_ON)); if (mScreenAutoBrightness != newScreenAutoBrightness) { if (DEBUG) { Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness=" @@ -507,6 +525,54 @@ class AutomaticBrightnessController { mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum); } + private void prepareBrightnessAdjustmentSample() { + if (!mBrightnessAdjustmentSamplePending) { + mBrightnessAdjustmentSamplePending = true; + mBrightnessAdjustmentSampleOldAdjustment = mScreenAutoBrightnessAdjustment; + mBrightnessAdjustmentSampleOldLux = mAmbientLuxValid ? mAmbientLux : -1; + mBrightnessAdjustmentSampleOldBrightness = mScreenAutoBrightness; + mBrightnessAdjustmentSampleOldGamma = mLastScreenAutoBrightnessGamma; + } else { + mHandler.removeMessages(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE); + } + + mHandler.sendEmptyMessageDelayed(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE, + BRIGHTNESS_ADJUSTMENT_SAMPLE_DEBOUNCE_MILLIS); + } + + private void cancelBrightnessAdjustmentSample() { + if (mBrightnessAdjustmentSamplePending) { + mBrightnessAdjustmentSamplePending = false; + mHandler.removeMessages(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE); + } + } + + private void collectBrightnessAdjustmentSample() { + if (mBrightnessAdjustmentSamplePending) { + mBrightnessAdjustmentSamplePending = false; + if (mAmbientLuxValid && mScreenAutoBrightness >= 0) { + if (DEBUG) { + Slog.d(TAG, "Auto-brightness adjustment changed by user: " + + "adj=" + mScreenAutoBrightnessAdjustment + + ", lux=" + mAmbientLux + + ", brightness=" + mScreenAutoBrightness + + ", gamma=" + mLastScreenAutoBrightnessGamma + + ", ring=" + mAmbientLightRingBuffer); + } + + EventLog.writeEvent(EventLogTags.AUTO_BRIGHTNESS_ADJ, + mBrightnessAdjustmentSampleOldAdjustment, + mBrightnessAdjustmentSampleOldLux, + mBrightnessAdjustmentSampleOldBrightness, + mBrightnessAdjustmentSampleOldGamma, + mScreenAutoBrightnessAdjustment, + mAmbientLux, + mScreenAutoBrightness, + mLastScreenAutoBrightnessGamma); + } + } + } + private static float getTwilightGamma(long now, long lastSunset, long nextSunrise) { if (lastSunset < 0 || nextSunrise < 0 || now < lastSunset || now > nextSunrise) { @@ -537,6 +603,10 @@ class AutomaticBrightnessController { case MSG_UPDATE_AMBIENT_LUX: updateAmbientLux(); break; + + case MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE: + collectBrightnessAdjustmentSample(); + break; } } } @@ -584,11 +654,7 @@ class AutomaticBrightnessController { private int mCount; public AmbientLightRingBuffer(long lightSensorRate) { - this((int) Math.ceil(AMBIENT_LIGHT_HORIZON * BUFFER_SLACK / lightSensorRate)); - } - - public AmbientLightRingBuffer(int initialCapacity) { - mCapacity = initialCapacity; + mCapacity = (int) Math.ceil(AMBIENT_LIGHT_HORIZON * BUFFER_SLACK / lightSensorRate); mRingLux = new float[mCapacity]; mRingTime = new long[mCapacity]; } @@ -664,10 +730,6 @@ class AutomaticBrightnessController { return mCount; } - public boolean isEmpty() { - return mCount == 0; - } - public void clear() { mStart = 0; mEnd = 0; @@ -676,27 +738,20 @@ class AutomaticBrightnessController { @Override public String toString() { - final int length = mCapacity - mStart; - float[] lux = new float[mCount]; - long[] time = new long[mCount]; - - if (mCount <= length) { - System.arraycopy(mRingLux, mStart, lux, 0, mCount); - System.arraycopy(mRingTime, mStart, time, 0, mCount); - } else { - System.arraycopy(mRingLux, mStart, lux, 0, length); - System.arraycopy(mRingLux, 0, lux, length, mCount - length); - - System.arraycopy(mRingTime, mStart, time, 0, length); - System.arraycopy(mRingTime, 0, time, length, mCount - length); + StringBuffer buf = new StringBuffer(); + buf.append('['); + for (int i = 0; i < mCount; i++) { + final long next = i + 1 < mCount ? getTime(i + 1) : SystemClock.uptimeMillis(); + if (i != 0) { + buf.append(", "); + } + buf.append(getLux(i)); + buf.append(" / "); + buf.append(next - getTime(i)); + buf.append("ms"); } - return "AmbientLightRingBuffer{mCapacity=" + mCapacity - + ", mStart=" + mStart - + ", mEnd=" + mEnd - + ", mCount=" + mCount - + ", mRingLux=" + Arrays.toString(lux) - + ", mRingTime=" + Arrays.toString(time) - + "}"; + buf.append(']'); + return buf.toString(); } private int offsetOf(int index) { diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index f74601e84d17..35fbef6d289f 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -70,12 +70,11 @@ import java.io.PrintWriter; */ final class DisplayPowerController implements AutomaticBrightnessController.Callbacks { private static final String TAG = "DisplayPowerController"; + private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked"; private static boolean DEBUG = false; private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false; - private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked"; - // If true, uses the color fade on animation. // We might want to turn this off if we cannot get a guarantee that the screen // actually turns on and starts showing new content after the call to set the @@ -599,8 +598,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call autoBrightnessEnabled = mPowerRequest.useAutoBrightness && (state == Display.STATE_ON || autoBrightnessEnabledInDoze) && brightness < 0; + final boolean userInitiatedChange = autoBrightnessAdjustmentChanged + && mPowerRequest.brightnessSetByUser; mAutomaticBrightnessController.configure(autoBrightnessEnabled, - mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON); + mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON, + userInitiatedChange); } // Apply brightness boost. diff --git a/services/core/java/com/android/server/display/WifiDisplayController.java b/services/core/java/com/android/server/display/WifiDisplayController.java index 31c1eeaad7a9..8932ca0cf85b 100644 --- a/services/core/java/com/android/server/display/WifiDisplayController.java +++ b/services/core/java/com/android/server/display/WifiDisplayController.java @@ -775,7 +775,7 @@ final class WifiDisplayController implements DumpUtils.Dump { handleConnectionFailure(false); } } - }, mHandler); + }, mHandler, mContext.getOpPackageName()); // Use extended timeout value for certification, as some tests require user inputs int rtspTimeout = mWifiDisplayCertMode ? diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java index 53ceb2e5d0c8..b066d6bb46d0 100644 --- a/services/core/java/com/android/server/job/JobServiceContext.java +++ b/services/core/java/com/android/server/job/JobServiceContext.java @@ -68,7 +68,7 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne private static final int defaultMaxActiveJobsPerService = ActivityManager.isLowRamDeviceStatic() ? 1 : 3; /** Amount of time a job is allowed to execute for before being considered timed-out. */ - private static final long EXECUTING_TIMESLICE_MILLIS = 60 * 1000; + private static final long EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000; /** Amount of time the JobScheduler will wait for a response from an app for a message. */ private static final long OP_TIMEOUT_MILLIS = 8 * 1000; diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 818f0aa0b36e..e45092c0b605 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -110,13 +110,16 @@ import android.os.Binder; import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; +import android.os.IDeviceIdleController; import android.os.INetworkManagementService; import android.os.IPowerManager; import android.os.Message; import android.os.MessageQueue.IdleHandler; +import android.os.PowerManager; import android.os.PowerManagerInternal; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -138,6 +141,7 @@ import android.util.TrustedTime; import android.util.Xml; import com.android.server.AppOpsService; +import com.android.server.DeviceIdleController; import libcore.io.IoUtils; import com.android.internal.R; @@ -245,6 +249,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private IConnectivityManager mConnManager; private INotificationManager mNotifManager; private PowerManagerInternal mPowerManagerInternal; + private IDeviceIdleController mDeviceIdleController; final Object mRulesLock = new Object(); @@ -321,6 +326,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mPowerManager = checkNotNull(powerManager, "missing powerManager"); mNetworkStats = checkNotNull(networkStats, "missing networkStats"); mNetworkManager = checkNotNull(networkManagement, "missing networkManagement"); + mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService( + DeviceIdleController.SERVICE_NAME)); mTime = checkNotNull(time, "missing TrustedTime"); HandlerThread thread = new HandlerThread(TAG); @@ -342,28 +349,27 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mNotifManager = checkNotNull(notifManager, "missing INotificationManager"); } + void updatePowerSaveWhitelistLocked() { + try { + final int[] whitelist = mDeviceIdleController.getAppIdWhitelist(); + mPowerSaveWhitelistAppIds.clear(); + if (whitelist != null) { + for (int uid : whitelist) { + mPowerSaveWhitelistAppIds.put(uid, true); + } + } + } catch (RemoteException e) { + } + } + public void systemReady() { if (!isBandwidthControlEnabled()) { Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy"); return; } - final PackageManager pm = mContext.getPackageManager(); - synchronized (mRulesLock) { - SystemConfig sysConfig = SystemConfig.getInstance(); - ArraySet<String> allowPower = sysConfig.getAllowInPowerSave(); - for (int i=0; i<allowPower.size(); i++) { - String pkg = allowPower.valueAt(i); - try { - ApplicationInfo ai = pm.getApplicationInfo(pkg, 0); - if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) { - mPowerSaveWhitelistAppIds.put(UserHandle.getAppId(ai.uid), true); - } - } catch (PackageManager.NameNotFoundException e) { - } - } - + updatePowerSaveWhitelistLocked(); mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mPowerManagerInternal.registerLowPowerModeObserver( new PowerManagerInternal.LowPowerModeListener() { @@ -406,6 +412,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { screenFilter.addAction(Intent.ACTION_SCREEN_OFF); mContext.registerReceiver(mScreenReceiver, screenFilter); + // listen for changes to power save whitelist + final IntentFilter whitelistFilter = new IntentFilter( + PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); + mContext.registerReceiver(mPowerSaveWhitelistReceiver, whitelistFilter, null, mHandler); + // watch for network interfaces to be claimed final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION); mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); @@ -489,6 +500,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }; + private BroadcastReceiver mPowerSaveWhitelistReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + // on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected + synchronized (mRulesLock) { + updatePowerSaveWhitelistLocked(); + updateRulesForGlobalChangeLocked(false); + } + } + }; + private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -1528,20 +1550,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return uids; } - @Override - public int[] getPowerSaveAppIdWhitelist() { - mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); - - synchronized (mRulesLock) { - int size = mPowerSaveWhitelistAppIds.size(); - int[] appids = new int[size]; - for (int i = 0; i < size; i++) { - appids[i] = mPowerSaveWhitelistAppIds.keyAt(i); - } - return appids; - } - } - /** * Remove any policies associated with given {@link UserHandle}, persisting * if any changes are made. diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java index 1e318ef3c487..44fbd2deee12 100644 --- a/services/core/java/com/android/server/notification/ZenLog.java +++ b/services/core/java/com/android/server/notification/ZenLog.java @@ -115,8 +115,8 @@ public class ZenLog { append(TYPE_UNSUBSCRIBE, uri + "," + subscribeResult(provider, e)); } - public static void traceConfig(ZenModeConfig oldConfig, ZenModeConfig newConfig) { - append(TYPE_CONFIG, newConfig != null ? newConfig.toString() : null); + public static void traceConfig(String reason, ZenModeConfig newConfig) { + append(TYPE_CONFIG, reason + "," + (newConfig != null ? newConfig.toString() : null)); } public static void traceDisableEffects(NotificationRecord record, String reason) { diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 9cb8af508744..83f0bcfc14c5 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -17,6 +17,7 @@ package com.android.server.notification; import static android.media.AudioAttributes.USAGE_ALARM; +import static android.media.AudioAttributes.USAGE_MEDIA; import static android.media.AudioAttributes.USAGE_NOTIFICATION; import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE; @@ -262,8 +263,8 @@ public class ZenModeHelper { } mConditions.evaluateConfig(config); // may modify config if (config.equals(mConfig)) return true; - if (DEBUG) Log.d(TAG, "setConfig reason=" + reason); - ZenLog.traceConfig(mConfig, config); + if (DEBUG) Log.d(TAG, "setConfig reason=" + reason, new Throwable()); + ZenLog.traceConfig(reason, config); final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig), getNotificationPolicy(config)); mConfig = config; @@ -329,9 +330,10 @@ public class ZenModeHelper { || mEffectsSuppressed; applyRestrictions(muteCalls, USAGE_NOTIFICATION_RINGTONE); - // alarm restrictions - final boolean muteAlarms = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS; - applyRestrictions(muteAlarms, USAGE_ALARM); + // alarm/media restrictions + final boolean zenNone = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS; + applyRestrictions(zenNone, USAGE_ALARM); + applyRestrictions(zenNone, USAGE_MEDIA); } private void applyRestrictions(boolean mute, int usage) { @@ -590,6 +592,11 @@ public class ZenModeHelper { ringerModeInternal, ringerModeInternalOut); return ringerModeInternalOut; } + + @Override + public boolean canVolumeDownEnterSilent() { + return mZenMode == Global.ZEN_MODE_OFF; + } } private final class SettingsObserver extends ContentObserver { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index f087c33645a8..8a190568509f 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -49,6 +49,7 @@ import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATIO import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; +import static android.content.pm.PackageManager.MATCH_ALL; import static android.content.pm.PackageManager.MOVE_FAILED_DOESNT_EXIST; import static android.content.pm.PackageManager.MOVE_FAILED_INTERNAL_ERROR; import static android.content.pm.PackageManager.MOVE_FAILED_OPERATION_PENDING; @@ -2274,6 +2275,13 @@ public class PackageManagerService extends IPackageManager.Stub { } continue; } + if (!pkg.isSystemApp()) { + if (logging) { + Slog.d(TAG, "No priming domain verifications for a non system package : " + + packageName); + } + continue; + } for (PackageParser.Activity a : pkg.activities) { for (ActivityIntentInfo filter : a.intents) { if (hasValidDomains(filter, false)) { @@ -2281,7 +2289,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } } - if (allHosts.size() > 0) { + if (allHosts.size() == 0) { allHosts.add("*"); } IntentFilterVerificationInfo ivi = @@ -3921,25 +3929,26 @@ public class PackageManagerService extends IPackageManager.Stub { // Check for results that need to skip the current profile. ResolveInfo resolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent, resolvedType, flags, userId); - if (resolveInfo != null) { + if (resolveInfo != null && isUserEnabled(resolveInfo.targetUserId)) { List<ResolveInfo> result = new ArrayList<ResolveInfo>(1); result.add(resolveInfo); return filterIfNotPrimaryUser(result, userId); } - // Check for cross profile results. - resolveInfo = queryCrossProfileIntents( - matchingFilters, intent, resolvedType, flags, userId); // Check for results in the current profile. List<ResolveInfo> result = mActivities.queryIntent( intent, resolvedType, flags, userId); - if (resolveInfo != null) { + + // Check for cross profile results. + resolveInfo = queryCrossProfileIntents( + matchingFilters, intent, resolvedType, flags, userId); + if (resolveInfo != null && isUserEnabled(resolveInfo.targetUserId)) { result.add(resolveInfo); Collections.sort(result, mResolvePrioritySorter); } result = filterIfNotPrimaryUser(result, userId); if (result.size() > 1 && hasWebURI(intent)) { - return filterCandidatesWithDomainPreferedActivitiesLPr(result); + return filterCandidatesWithDomainPreferedActivitiesLPr(flags, result); } return result; } @@ -3954,6 +3963,16 @@ public class PackageManagerService extends IPackageManager.Stub { } } + private boolean isUserEnabled(int userId) { + long callingId = Binder.clearCallingIdentity(); + try { + UserInfo userInfo = sUserManager.getUserInfo(userId); + return userInfo != null && userInfo.isEnabled(); + } finally { + Binder.restoreCallingIdentity(callingId); + } + } + /** * Filter out activities with primaryUserOnly flag set, when current user is not the owner. * @@ -3984,7 +4003,7 @@ public class PackageManagerService extends IPackageManager.Stub { } private List<ResolveInfo> filterCandidatesWithDomainPreferedActivitiesLPr( - List<ResolveInfo> candidates) { + int flags, List<ResolveInfo> candidates) { if (DEBUG_PREFERRED) { Slog.v("TAG", "Filtering results with prefered activities. Candidates count: " + candidates.size()); @@ -4004,6 +4023,11 @@ public class PackageManagerService extends IPackageManager.Stub { String packageName = info.activityInfo.packageName; PackageSetting ps = mSettings.mPackages.get(packageName); if (ps != null) { + // Add to the special match all list (Browser use case) + if (info.handleAllWebDataURI) { + matchAllList.add(info); + continue; + } // Try to get the status from User settings first int status = getDomainVerificationStatusLPr(ps, userId); if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) { @@ -4013,10 +4037,6 @@ public class PackageManagerService extends IPackageManager.Stub { } else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) { undefinedList.add(info); } - // Add to the special match all list (Browser use case) - if (info.handleAllWebDataURI) { - matchAllList.add(info); - } } } // If there is nothing selected, add all candidates and remove the ones that the User @@ -4031,7 +4051,30 @@ public class PackageManagerService extends IPackageManager.Stub { result.removeAll(matchAllList); if (result.size() == 0) { result.addAll(undefinedList); - result.addAll(matchAllList); + if ((flags & MATCH_ALL) != 0) { + result.addAll(matchAllList); + } else { + // Try to add the Default Browser if we can + final String defaultBrowserPackageName = getDefaultBrowserPackageName( + UserHandle.myUserId()); + if (!TextUtils.isEmpty(defaultBrowserPackageName)) { + boolean defaultBrowserFound = false; + final int browserCount = matchAllList.size(); + for (int n=0; n<browserCount; n++) { + ResolveInfo browser = matchAllList.get(n); + if (browser.activityInfo.packageName.equals(defaultBrowserPackageName)) { + result.add(browser); + defaultBrowserFound = true; + break; + } + } + if (!defaultBrowserFound) { + result.addAll(matchAllList); + } + } else { + result.addAll(matchAllList); + } + } } } if (DEBUG_PREFERRED) { @@ -11331,10 +11374,16 @@ public class PackageManagerService extends IPackageManager.Stub { verifierUid, userId, verificationId, filter, packageName); count++; } else if (!needsFilterVerification) { - Slog.d(TAG, "No verification needed for IntentFilter:" - + filter.toString()); + Slog.d(TAG, "No verification needed for IntentFilter:" + filter.toString()); if (hasValidDomains(filter)) { - allHosts.addAll(filter.getHostsList()); + ArrayList<String> hosts = filter.getHostsList(); + if (hosts.size() > 0) { + allHosts.addAll(hosts); + } else { + if (allHosts.isEmpty()) { + allHosts.add("*"); + } + } } } else { Slog.d(TAG, "Verification already done for IntentFilter:" @@ -14154,7 +14203,8 @@ public class PackageManagerService extends IPackageManager.Stub { movePackageInternal(packageName, volumeUuid, moveId); } catch (PackageManagerException e) { Slog.d(TAG, "Failed to move " + packageName, e); - mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_FAILED_INTERNAL_ERROR); + mMoveCallbacks.notifyStatusChanged(moveId, null, + PackageManager.MOVE_FAILED_INTERNAL_ERROR); } return moveId; } @@ -14171,6 +14221,7 @@ public class PackageManagerService extends IPackageManager.Stub { final String packageAbiOverride; final int appId; final String seinfo; + final String moveTitle; // reader synchronized (mPackages) { @@ -14190,9 +14241,6 @@ public class PackageManagerService extends IPackageManager.Stub { // TODO: yell if already in desired location - mMoveCallbacks.notifyStarted(moveId, - String.valueOf(pm.getApplicationLabel(pkg.applicationInfo))); - pkg.mOperationPending = true; currentAsec = pkg.applicationInfo.isForwardLocked() @@ -14203,6 +14251,7 @@ public class PackageManagerService extends IPackageManager.Stub { packageAbiOverride = ps.cpuAbiOverrideString; appId = UserHandle.getAppId(pkg.applicationInfo.uid); seinfo = pkg.applicationInfo.seinfo; + moveTitle = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo)); } int installFlags; @@ -14230,7 +14279,7 @@ public class PackageManagerService extends IPackageManager.Stub { } Slog.d(TAG, "Moving " + packageName + " from " + currentVolumeUuid + " to " + volumeUuid); - mMoveCallbacks.notifyStatusChanged(moveId, 10, -1); + mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, 10); if (moveData) { synchronized (mInstallLock) { @@ -14250,7 +14299,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } - mMoveCallbacks.notifyStatusChanged(moveId, 50); + mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, 50); final IPackageInstallObserver2 installObserver = new IPackageInstallObserver2.Stub() { @Override @@ -14277,15 +14326,15 @@ public class PackageManagerService extends IPackageManager.Stub { final int status = PackageManager.installStatusToPublicStatus(returnCode); switch (status) { case PackageInstaller.STATUS_SUCCESS: - mMoveCallbacks.notifyStatusChanged(moveId, + mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, PackageManager.MOVE_SUCCEEDED); break; case PackageInstaller.STATUS_FAILURE_STORAGE: - mMoveCallbacks.notifyStatusChanged(moveId, + mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE); break; default: - mMoveCallbacks.notifyStatusChanged(moveId, + mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, PackageManager.MOVE_FAILED_INTERNAL_ERROR); break; } @@ -14308,15 +14357,12 @@ public class PackageManagerService extends IPackageManager.Stub { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null); final int realMoveId = mNextMoveId.getAndIncrement(); - final IPackageMoveObserver callback = new IPackageMoveObserver.Stub() { - @Override - public void onStarted(int moveId, String title) { - // Ignored - } + final String realTitle = null; + final IPackageMoveObserver callback = new IPackageMoveObserver.Stub() { @Override - public void onStatusChanged(int moveId, int status, long estMillis) { - mMoveCallbacks.notifyStatusChanged(realMoveId, status, estMillis); + public void onStatusChanged(int moveId, String title, int status, long estMillis) { + mMoveCallbacks.notifyStatusChanged(realMoveId, realTitle, status, estMillis); } }; @@ -14671,7 +14717,6 @@ public class PackageManagerService extends IPackageManager.Stub { } private static class MoveCallbacks extends Handler { - private static final int MSG_STARTED = 1; private static final int MSG_STATUS_CHANGED = 2; private final RemoteCallbackList<IPackageMoveObserver> @@ -14709,37 +14754,26 @@ public class PackageManagerService extends IPackageManager.Stub { private void invokeCallback(IPackageMoveObserver callback, int what, SomeArgs args) throws RemoteException { switch (what) { - case MSG_STARTED: { - callback.onStarted(args.argi1, (String) args.arg2); - break; - } case MSG_STATUS_CHANGED: { - callback.onStatusChanged(args.argi1, args.argi2, (long) args.arg3); + callback.onStatusChanged(args.argi1, (String) args.arg2, args.argi3, + (long) args.arg4); break; } } } - private void notifyStarted(int moveId, String title) { - Slog.v(TAG, "Move " + moveId + " started with title " + title); - - final SomeArgs args = SomeArgs.obtain(); - args.argi1 = moveId; - args.arg2 = title; - obtainMessage(MSG_STARTED, args).sendToTarget(); - } - - private void notifyStatusChanged(int moveId, int status) { - notifyStatusChanged(moveId, status, -1); + private void notifyStatusChanged(int moveId, String moveTitle, int status) { + notifyStatusChanged(moveId, moveTitle, status, -1); } - private void notifyStatusChanged(int moveId, int status, long estMillis) { + private void notifyStatusChanged(int moveId, String moveTitle, int status, long estMillis) { Slog.v(TAG, "Move " + moveId + " status " + status); final SomeArgs args = SomeArgs.obtain(); args.argi1 = moveId; - args.argi2 = status; - args.arg3 = estMillis; + args.arg2 = moveTitle; + args.argi3 = status; + args.arg4 = estMillis; obtainMessage(MSG_STATUS_CHANGED, args).sendToTarget(); synchronized (mLastStatus) { diff --git a/services/core/java/com/android/server/power/DeviceIdleController.java b/services/core/java/com/android/server/power/DeviceIdleController.java deleted file mode 100644 index 6b29b9a4a422..000000000000 --- a/services/core/java/com/android/server/power/DeviceIdleController.java +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Copyright (C) 2015 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.power; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.hardware.Sensor; -import android.hardware.SensorManager; -import android.hardware.TriggerEvent; -import android.hardware.TriggerEventListener; -import android.hardware.display.DisplayManager; -import android.net.INetworkPolicyManager; -import android.os.Binder; -import android.os.PowerManager; -import android.os.PowerManagerInternal; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.SystemClock; -import android.os.UserHandle; -import android.util.TimeUtils; -import android.view.Display; -import com.android.internal.app.IBatteryStats; -import com.android.server.SystemService; -import com.android.server.am.BatteryStatsService; -import com.android.server.EventLogTags; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * Keeps track of device idleness and drives low power mode based on that. - */ -public class DeviceIdleController extends SystemService { - private static final String TAG = "DeviceIdleController"; - - private static final String ACTION_STEP_IDLE_STATE = - "com.android.server.device_idle.STEP_IDLE_STATE"; - - // TODO: These need to be moved to system settings. - - /** - * This is the time, after becoming inactive, at which we start looking at the - * motion sensor to determine if the device is being left alone. We don't do this - * immediately after going inactive just because we don't want to be continually running - * the significant motion sensor whenever the screen is off. - */ - private static final long DEFAULT_INACTIVE_TIMEOUT = 30*60*1000L; - /** - * This is the time, after seeing motion, that we wait after becoming inactive from - * that until we start looking for motion again. - */ - private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = 10*60*1000L; - /** - * This is the time, after the inactive timeout elapses, that we will wait looking - * for significant motion until we truly consider the device to be idle. - */ - private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = 30*60*1000L; - /** - * This is the initial time, after being idle, that we will allow ourself to be back - * in the IDLE_PENDING state allowing the system to run normally until we return to idle. - */ - private static final long DEFAULT_IDLE_PENDING_TIMEOUT = 5*60*1000L; - /** - * Maximum pending idle timeout (time spent running) we will be allowed to use. - */ - private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT = 10*60*1000L; - /** - * Scaling factor to apply to current pending idle timeout each time we cycle through - * that state. - */ - private static final float DEFAULT_IDLE_PENDING_FACTOR = 2f; - /** - * This is the initial time that we want to sit in the idle state before waking up - * again to return to pending idle and allowing normal work to run. - */ - private static final long DEFAULT_IDLE_TIMEOUT = 60*60*1000L; - /** - * Maximum idle duration we will be allowed to use. - */ - private static final long DEFAULT_MAX_IDLE_TIMEOUT = 6*60*60*1000L; - /** - * Scaling factor to apply to current idle timeout each time we cycle through that state. - */ - private static final float DEFAULT_IDLE_FACTOR = 2f; - /** - * This is the minimum time we will allow until the next upcoming alarm for us to - * actually go in to idle mode. - */ - private static final long DEFAULT_MIN_TIME_TO_ALARM = 60*60*1000L; - - private AlarmManager mAlarmManager; - private IBatteryStats mBatteryStats; - private PowerManagerInternal mLocalPowerManager; - private INetworkPolicyManager mNetworkPolicyManager; - private DisplayManager mDisplayManager; - private SensorManager mSensorManager; - private Sensor mSigMotionSensor; - private PendingIntent mAlarmIntent; - private Intent mIdleIntent; - private Display mCurDisplay; - private boolean mScreenOn; - private boolean mCharging; - private boolean mSigMotionActive; - - /** Device is currently active. */ - private static final int STATE_ACTIVE = 0; - /** Device is inactve (screen off, no motion) and we are waiting to for idle. */ - private static final int STATE_INACTIVE = 1; - /** Device is past the initial inactive period, and waiting for the next idle period. */ - private static final int STATE_IDLE_PENDING = 2; - /** Device is in the idle state, trying to stay asleep as much as possible. */ - private static final int STATE_IDLE = 3; - private static String stateToString(int state) { - switch (state) { - case STATE_ACTIVE: return "ACTIVE"; - case STATE_INACTIVE: return "INACTIVE"; - case STATE_IDLE_PENDING: return "IDLE_PENDING"; - case STATE_IDLE: return "IDLE"; - default: return Integer.toString(state); - } - } - - private int mState; - - private long mInactiveTimeout; - private long mNextAlarmTime; - private long mNextIdlePendingDelay; - private long mNextIdleDelay; - - private final Binder mBinder = new Binder() { - @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - DeviceIdleController.this.dump(fd, pw, args); - } - }; - - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { - int plugged = intent.getIntExtra("plugged", 0); - updateChargingLocked(plugged != 0); - } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) { - synchronized (DeviceIdleController.this) { - stepIdleStateLocked(); - } - } - } - }; - - private final DisplayManager.DisplayListener mDisplayListener - = new DisplayManager.DisplayListener() { - @Override public void onDisplayAdded(int displayId) { - } - - @Override public void onDisplayRemoved(int displayId) { - } - - @Override public void onDisplayChanged(int displayId) { - if (displayId == Display.DEFAULT_DISPLAY) { - synchronized (DeviceIdleController.this) { - updateDisplayLocked(); - } - } - } - }; - - private final TriggerEventListener mSigMotionListener = new TriggerEventListener() { - @Override public void onTrigger(TriggerEvent event) { - synchronized (DeviceIdleController.this) { - significantMotionLocked(); - } - } - }; - - public DeviceIdleController(Context context) { - super(context); - } - - @Override - public void onStart() { - synchronized (this) { - mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); - mBatteryStats = BatteryStatsService.getService(); - mLocalPowerManager = getLocalService(PowerManagerInternal.class); - mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface( - ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)); - mDisplayManager = (DisplayManager) getContext().getSystemService( - Context.DISPLAY_SERVICE); - mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); - mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION); - - Intent intent = new Intent(ACTION_STEP_IDLE_STATE) - .setPackage("android") - .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0); - - mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); - mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_BATTERY_CHANGED); - filter.addAction(ACTION_STEP_IDLE_STATE); - getContext().registerReceiver(mReceiver, filter); - - mDisplayManager.registerDisplayListener(mDisplayListener, null); - - mScreenOn = true; - // Start out assuming we are charging. If we aren't, we will at least get - // a battery update the next time the level drops. - mCharging = true; - mState = STATE_ACTIVE; - mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT; - updateDisplayLocked(); - } - - publishBinderService("deviceidle", mBinder); - } - - void updateDisplayLocked() { - mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); - // We consider any situation where the display is showing something to be it on, - // because if there is anything shown we are going to be updating it at some - // frequency so can't be allowed to go into deep sleeps. - boolean screenOn = mCurDisplay.getState() != Display.STATE_OFF;; - if (!screenOn && mScreenOn) { - mScreenOn = false; - becomeInactiveIfAppropriateLocked(); - } else if (screenOn) { - mScreenOn = true; - becomeActiveLocked("screen"); - } - } - - void updateChargingLocked(boolean charging) { - if (!charging && mCharging) { - mCharging = false; - becomeInactiveIfAppropriateLocked(); - } else if (charging) { - mCharging = charging; - becomeActiveLocked("charging"); - } - } - - void becomeActiveLocked(String reason) { - if (mState != STATE_ACTIVE) { - EventLogTags.writeDeviceIdle(STATE_ACTIVE, reason); - mLocalPowerManager.setDeviceIdleMode(false); - try { - mNetworkPolicyManager.setDeviceIdleMode(false); - mBatteryStats.noteDeviceIdleMode(false, true, false); - } catch (RemoteException e) { - } - if (mState == STATE_IDLE) { - getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); - } - mState = STATE_ACTIVE; - mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT; - mNextIdlePendingDelay = 0; - mNextIdleDelay = 0; - cancelAlarmLocked(); - stopMonitoringSignificantMotion(); - } - } - - void becomeInactiveIfAppropriateLocked() { - if (!mScreenOn && !mCharging && mState == STATE_ACTIVE) { - // Screen has turned off; we are now going to become inactive and start - // waiting to see if we will ultimately go idle. - mState = STATE_INACTIVE; - mNextIdlePendingDelay = 0; - mNextIdleDelay = 0; - scheduleAlarmLocked(mInactiveTimeout, false); - EventLogTags.writeDeviceIdle(mState, "no activity"); - } - } - - void stepIdleStateLocked() { - EventLogTags.writeDeviceIdleStep(); - - final long now = SystemClock.elapsedRealtime(); - if ((now+DEFAULT_MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) { - // Whoops, there is an upcoming alarm. We don't actually want to go idle. - if (mState != STATE_ACTIVE) { - becomeActiveLocked("alarm"); - } - return; - } - - switch (mState) { - case STATE_INACTIVE: - // We have now been inactive long enough, it is time to start looking - // for significant motion and sleep some more while doing so. - startMonitoringSignificantMotion(); - scheduleAlarmLocked(DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT, false); - // Reset the upcoming idle delays. - mNextIdlePendingDelay = DEFAULT_IDLE_PENDING_TIMEOUT; - mNextIdleDelay = DEFAULT_IDLE_TIMEOUT; - mState = STATE_IDLE_PENDING; - EventLogTags.writeDeviceIdle(mState, "step"); - break; - case STATE_IDLE_PENDING: - // We have been waiting to become idle, and now it is time! This is the - // only case where we want to use a wakeup alarm, because we do want to - // drag the device out of its sleep state in this case to do the next - // scheduled work. - scheduleAlarmLocked(mNextIdleDelay, true); - mNextIdleDelay = (long)(mNextIdleDelay*DEFAULT_IDLE_FACTOR); - if (mNextIdleDelay > DEFAULT_MAX_IDLE_TIMEOUT) { - mNextIdleDelay = DEFAULT_MAX_IDLE_TIMEOUT; - } - mState = STATE_IDLE; - EventLogTags.writeDeviceIdle(mState, "step"); - mLocalPowerManager.setDeviceIdleMode(true); - try { - mNetworkPolicyManager.setDeviceIdleMode(true); - mBatteryStats.noteDeviceIdleMode(true, false, false); - } catch (RemoteException e) { - } - getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); - break; - case STATE_IDLE: - // We have been idling long enough, now it is time to do some work. - scheduleAlarmLocked(mNextIdlePendingDelay, false); - mNextIdlePendingDelay = (long)(mNextIdlePendingDelay*DEFAULT_IDLE_PENDING_FACTOR); - if (mNextIdlePendingDelay > DEFAULT_MAX_IDLE_PENDING_TIMEOUT) { - mNextIdlePendingDelay = DEFAULT_MAX_IDLE_PENDING_TIMEOUT; - } - mState = STATE_IDLE_PENDING; - EventLogTags.writeDeviceIdle(mState, "step"); - mLocalPowerManager.setDeviceIdleMode(false); - try { - mNetworkPolicyManager.setDeviceIdleMode(false); - mBatteryStats.noteDeviceIdleMode(false, false, false); - } catch (RemoteException e) { - } - getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); - break; - } - } - - void significantMotionLocked() { - // When the sensor goes off, its trigger is automatically removed. - mSigMotionActive = false; - // The device is not yet active, so we want to go back to the pending idle - // state to wait again for no motion. Note that we only monitor for significant - // motion after moving out of the inactive state, so no need to worry about that. - if (mState != STATE_ACTIVE) { - mLocalPowerManager.setDeviceIdleMode(false); - try { - mNetworkPolicyManager.setDeviceIdleMode(false); - mBatteryStats.noteDeviceIdleMode(false, false, true); - } catch (RemoteException e) { - } - if (mState == STATE_IDLE) { - getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); - } - mState = STATE_ACTIVE; - mInactiveTimeout = DEFAULT_MOTION_INACTIVE_TIMEOUT; - EventLogTags.writeDeviceIdle(mState, "motion"); - becomeInactiveIfAppropriateLocked(); - } - } - - void startMonitoringSignificantMotion() { - if (mSigMotionSensor != null && !mSigMotionActive) { - mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor); - mSigMotionActive = true; - } - } - - void stopMonitoringSignificantMotion() { - if (mSigMotionActive) { - mSensorManager.cancelTriggerSensor(mSigMotionListener, mSigMotionSensor); - mSigMotionActive = false; - } - } - - void cancelAlarmLocked() { - if (mNextAlarmTime != 0) { - mNextAlarmTime = 0; - mAlarmManager.cancel(mAlarmIntent); - } - } - - void scheduleAlarmLocked(long delay, boolean idleUntil) { - if (mSigMotionSensor == null) { - // If there is no significant motion sensor on this device, then we won't schedule - // alarms, because we can't determine if the device is not moving. This effectively - // turns off normal exeuction of device idling, although it is still possible to - // manually poke it by pretending like the alarm is going off. - return; - } - mNextAlarmTime = SystemClock.elapsedRealtime() + delay; - if (idleUntil) { - mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mNextAlarmTime, mAlarmIntent); - } else { - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mNextAlarmTime, mAlarmIntent); - } - } - - private void dumpHelp(PrintWriter pw) { - pw.println("Device idle controller (deviceidle) dump options:"); - pw.println(" [-h] [CMD]"); - pw.println(" -h: print this help text."); - pw.println("Commands:"); - pw.println(" step"); - pw.println(" Immediately step to next state, without waiting for alarm."); - } - - void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump DeviceIdleController from from pid=" - + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() - + " without permission " + android.Manifest.permission.DUMP); - return; - } - - if (args != null) { - for (int i=0; i<args.length; i++) { - String arg = args[i]; - if ("-h".equals(arg)) { - dumpHelp(pw); - return; - } else if ("step".equals(arg)) { - synchronized (this) { - stepIdleStateLocked(); - pw.print("Stepped to: "); pw.println(stateToString(mState)); - } - return; - } else if (arg.length() > 0 && arg.charAt(0) == '-'){ - pw.println("Unknown option: " + arg); - dumpHelp(pw); - return; - } else { - pw.println("Unknown command: " + arg); - dumpHelp(pw); - return; - } - } - } - - synchronized (this) { - pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor); - pw.print(" mCurDisplay="); pw.println(mCurDisplay); - pw.print(" mScreenOn="); pw.println(mScreenOn); - pw.print(" mCharging="); pw.println(mCharging); - pw.print(" mSigMotionActive="); pw.println(mSigMotionActive); - pw.print(" mState="); pw.println(stateToString(mState)); - pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw); - pw.println(); - if (mNextAlarmTime != 0) { - pw.print(" mNextAlarmTime="); - TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw); - pw.println(); - } - if (mNextIdlePendingDelay != 0) { - pw.print(" mNextIdlePendingDelay="); - TimeUtils.formatDuration(mNextIdlePendingDelay, pw); - pw.println(); - } - if (mNextIdleDelay != 0) { - pw.print(" mNextIdleDelay="); - TimeUtils.formatDuration(mNextIdleDelay, pw); - pw.println(); - } - } - } -} diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 6c8959c933d9..f790f75096da 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -1819,6 +1819,7 @@ public final class PowerManagerService extends SystemService mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked(); // Determine appropriate screen brightness and auto-brightness adjustments. + boolean brightnessSetByUser = true; int screenBrightness = mScreenBrightnessSettingDefault; float screenAutoBrightnessAdjustment = 0.0f; boolean autoBrightness = (mScreenBrightnessModeSetting == @@ -1826,6 +1827,7 @@ public final class PowerManagerService extends SystemService if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) { screenBrightness = mScreenBrightnessOverrideFromWindowManager; autoBrightness = false; + brightnessSetByUser = false; } else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) { screenBrightness = mTemporaryScreenBrightnessSettingOverride; } else if (isValidBrightness(mScreenBrightnessSetting)) { @@ -1851,6 +1853,7 @@ public final class PowerManagerService extends SystemService mDisplayPowerRequest.screenBrightness = screenBrightness; mDisplayPowerRequest.screenAutoBrightnessAdjustment = screenAutoBrightnessAdjustment; + mDisplayPowerRequest.brightnessSetByUser = brightnessSetByUser; mDisplayPowerRequest.useAutoBrightness = autoBrightness; mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked(); mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled; diff --git a/services/core/jni/com_android_server_UsbHostManager.cpp b/services/core/jni/com_android_server_UsbHostManager.cpp index ee50ff9ec38b..d8c172fd51cc 100644 --- a/services/core/jni/com_android_server_UsbHostManager.cpp +++ b/services/core/jni/com_android_server_UsbHostManager.cpp @@ -71,6 +71,7 @@ static int usb_device_added(const char *devname, void* client_data) { char *manufacturer = usb_device_get_manufacturer_name(device); char *product = usb_device_get_product_name(device); + int version = usb_device_get_version(device); char *serial = usb_device_get_serial(device); jstring deviceName = env->NewStringUTF(devname); @@ -81,7 +82,7 @@ static int usb_device_added(const char *devname, void* client_data) { jboolean result = env->CallBooleanMethod(thiz, method_beginUsbDeviceAdded, deviceName, usb_device_get_vendor_id(device), usb_device_get_product_id(device), deviceDesc->bDeviceClass, deviceDesc->bDeviceSubClass, deviceDesc->bDeviceProtocol, - manufacturerName, productName, serialNumber); + manufacturerName, productName, version, serialNumber); env->DeleteLocalRef(serialNumber); env->DeleteLocalRef(productName); @@ -199,7 +200,7 @@ int register_android_server_UsbHostManager(JNIEnv *env) return -1; } method_beginUsbDeviceAdded = env->GetMethodID(clazz, "beginUsbDeviceAdded", - "(Ljava/lang/String;IIIIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z"); + "(Ljava/lang/String;IIIIILjava/lang/String;Ljava/lang/String;ILjava/lang/String;)Z"); if (method_beginUsbDeviceAdded == NULL) { ALOGE("Can't find beginUsbDeviceAdded"); return -1; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 31d7f7444cfd..f801d2d2fb2c 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -182,6 +182,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final String ATTR_PERMISSION_PROVIDER = "permission-provider"; private static final String ATTR_SETUP_COMPLETE = "setup-complete"; private static final String ATTR_PREFERRED_SETUP_ACTIVITY = "setup-activity"; + private static final String ATTR_PERMISSION_POLICY = "permission-policy"; private static final String ATTR_DELEGATED_CERT_INSTALLER = "delegated-cert-installer"; @@ -191,6 +192,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { StatusBarManager.DISABLE_NOTIFICATION_ALERTS | StatusBarManager.DISABLE_SEARCH; + private static final int STATUS_BAR_DISABLE2_MASK = + StatusBarManager.DISABLE2_QUICK_SETTINGS; + private static final Set<String> DEVICE_OWNER_USER_RESTRICTIONS; static { DEVICE_OWNER_USER_RESTRICTIONS = new HashSet(); @@ -300,6 +304,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int mPasswordOwner = -1; long mLastMaximumTimeToLock = -1; boolean mUserSetupComplete = false; + int mPermissionPolicy; final HashMap<ComponentName, ActiveAdmin> mAdminMap = new HashMap<>(); final ArrayList<ActiveAdmin> mAdminList = new ArrayList<>(); @@ -1409,6 +1414,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.attribute(null, ATTR_SETUP_COMPLETE, Boolean.toString(true)); } + if (policy.mPermissionPolicy != DevicePolicyManager.PERMISSION_POLICY_PROMPT) { + out.attribute(null, ATTR_PERMISSION_POLICY, + Integer.toString(policy.mPermissionPolicy)); + } if (policy.mDelegatedCertInstallerPackage != null) { out.attribute(null, ATTR_DELEGATED_CERT_INSTALLER, policy.mDelegatedCertInstallerPackage); @@ -1537,6 +1546,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (userSetupComplete != null && Boolean.toString(true).equals(userSetupComplete)) { policy.mUserSetupComplete = true; } + String permissionPolicy = parser.getAttributeValue(null, ATTR_PERMISSION_POLICY); + if (!TextUtils.isEmpty(permissionPolicy)) { + policy.mPermissionPolicy = Integer.parseInt(permissionPolicy); + } policy.mDelegatedCertInstallerPackage = parser.getAttributeValue(null, ATTR_DELEGATED_CERT_INSTALLER); String preferredSetupActivity = @@ -4253,14 +4266,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return; } UserHandle callingUser = Binder.getCallingUserHandle(); + int userId = callingUser.getIdentifier(); // Check if this is the profile owner who is calling getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); synchronized (this) { + // Reset some of the profile-owner policies + DevicePolicyData policy = getUserData(userId); + policy.mPermissionPolicy = DevicePolicyManager.PERMISSION_POLICY_PROMPT; + policy.mDelegatedCertInstallerPackage = null; + policy.mStatusBarEnabledState = true; + saveSettingsLocked(userId); + long ident = Binder.clearCallingIdentity(); try { clearUserRestrictions(callingUser); if (mDeviceOwner != null) { - mDeviceOwner.removeProfileOwner(callingUser.getIdentifier()); + mDeviceOwner.removeProfileOwner(userId); mDeviceOwner.writeOwnerFile(); } } finally { @@ -6022,8 +6043,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { IStatusBarService statusBarService = IStatusBarService.Stub.asInterface( ServiceManager.checkService(Context.STATUS_BAR_SERVICE)); if (statusBarService != null) { - int flags = enabled ? StatusBarManager.DISABLE_NONE : STATUS_BAR_DISABLE_MASK; - statusBarService.disableForUser(flags, mToken, mContext.getPackageName(), userId); + int flags1 = enabled ? StatusBarManager.DISABLE_NONE : STATUS_BAR_DISABLE_MASK; + int flags2 = enabled ? StatusBarManager.DISABLE2_NONE : STATUS_BAR_DISABLE2_MASK; + statusBarService.disableForUser(flags1, mToken, mContext.getPackageName(), userId); + statusBarService.disable2ForUser(flags2, mToken, mContext.getPackageName(), userId); } } catch (RemoteException e) { Slog.e(LOG_TAG, "Failed to disable the status bar", e); @@ -6261,4 +6284,48 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } + + @Override + public void setPermissionPolicy(ComponentName admin, int policy) throws RemoteException { + int userId = UserHandle.getCallingUserId(); + synchronized (this) { + getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + DevicePolicyData userPolicy = getUserData(userId); + if (userPolicy.mPermissionPolicy != policy) { + userPolicy.mPermissionPolicy = policy; + saveSettingsLocked(userId); + } + } + } + + @Override + public int getPermissionPolicy(ComponentName admin) throws RemoteException { + int userId = UserHandle.getCallingUserId(); + synchronized (this) { + DevicePolicyData userPolicy = getUserData(userId); + return userPolicy.mPermissionPolicy; + } + } + + @Override + public boolean setPermissionGranted(ComponentName admin, String packageName, + String permission, boolean granted) throws RemoteException { + UserHandle user = Binder.getCallingUserHandle(); + synchronized (this) { + getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + long ident = Binder.clearCallingIdentity(); + try { + if (granted) { + mContext.getPackageManager().grantPermission(packageName, permission, user); + } else { + mContext.getPackageManager().revokePermission(packageName, permission, user); + } + return true; + } catch (SecurityException se) { + return false; + } finally { + Binder.restoreCallingIdentity(ident); + } + } + } } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 593853c17263..29221305fc86 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -76,7 +76,6 @@ import com.android.server.pm.Installer; import com.android.server.pm.LauncherAppsService; import com.android.server.pm.PackageManagerService; import com.android.server.pm.UserManagerService; -import com.android.server.power.DeviceIdleController; import com.android.server.power.PowerManagerService; import com.android.server.power.ShutdownThread; import com.android.server.restrictions.RestrictionsManagerService; @@ -599,6 +598,8 @@ public final class SystemServer { mSystemServiceManager.startService(PersistentDataBlockService.class); } + mSystemServiceManager.startService(DeviceIdleController.class); + // Always start the Device Policy Manager, so that the API is compatible with // API8. mSystemServiceManager.startService(DevicePolicyManagerService.Lifecycle.class); @@ -965,7 +966,6 @@ public final class SystemServer { if (!disableNonCoreServices) { mSystemServiceManager.startService(MediaProjectionManagerService.class); - mSystemServiceManager.startService(DeviceIdleController.class); } // Before things start rolling, be sure we have decided whether diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java index daccf959cadb..27c97d0af2f7 100644 --- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java +++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java @@ -401,6 +401,7 @@ public final class UsbAlsaManager { Bundle properties = new Bundle(); String manufacturer = usbDevice.getManufacturerName(); String product = usbDevice.getProductName(); + String version = usbDevice.getVersion(); String name; if (manufacturer == null || manufacturer.isEmpty()) { name = product; @@ -412,6 +413,7 @@ public final class UsbAlsaManager { properties.putString(MidiDeviceInfo.PROPERTY_NAME, name); properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, manufacturer); properties.putString(MidiDeviceInfo.PROPERTY_PRODUCT, product); + properties.putString(MidiDeviceInfo.PROPERTY_VERSION, version); properties.putString(MidiDeviceInfo.PROPERTY_SERIAL_NUMBER, usbDevice.getSerialNumber()); properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, alsaDevice.mCard); diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java index 5b580511096a..f5f2b07e3e93 100644 --- a/services/usb/java/com/android/server/usb/UsbHostManager.java +++ b/services/usb/java/com/android/server/usb/UsbHostManager.java @@ -112,7 +112,7 @@ public class UsbHostManager { */ private boolean beginUsbDeviceAdded(String deviceName, int vendorID, int productID, int deviceClass, int deviceSubclass, int deviceProtocol, - String manufacturerName, String productName, String serialNumber) { + String manufacturerName, String productName, int version, String serialNumber) { if (DEBUG) { Slog.d(TAG, "usb:UsbHostManager.beginUsbDeviceAdded(" + deviceName + ")"); @@ -149,9 +149,12 @@ public class UsbHostManager { return false; } + // Create version string in "%.%" format + String versionString = Integer.toString(version >> 8) + "." + (version & 0xFF); + mNewDevice = new UsbDevice(deviceName, vendorID, productID, deviceClass, deviceSubclass, deviceProtocol, - manufacturerName, productName, serialNumber); + manufacturerName, productName, versionString, serialNumber); mNewConfigurations = new ArrayList<UsbConfiguration>(); mNewInterfaces = new ArrayList<UsbInterface>(); diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 831a19460525..299c7c446b76 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -48,33 +48,147 @@ public class CarrierConfigManager { ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED"; /** - * Flag specifying whether VoLTE should be available for carrier, independent of carrier - * provisioning. If false: hard disabled. If true: then depends on carrier provisioning, - * availability, etc. + * Flag indicating whether the Phone app should ignore EVENT_SIM_NETWORK_LOCKED + * events from the Sim. + * If true, this will prevent the IccNetworkDepersonalizationPanel from being shown, and + * effectively disable the "Sim network lock" feature. */ - public static final String BOOL_CARRIER_VOLTE_AVAILABLE = "bool_carrier_volte_available"; + public static final String + BOOL_IGNORE_SIM_NETWORK_LOCKED_EVENTS = "bool_ignore_sim_network_locked_events"; /** - * Flag specifying whether VoLTE availability is based on provisioning. + * Flag indicating whether the Phone app should provide a "Dismiss" button on the SIM network + * unlock screen. The default value is true. If set to false, there will be *no way* to dismiss + * the SIM network unlock screen if you don't enter the correct unlock code. (One important + * consequence: there will be no way to make an Emergency Call if your SIM is network-locked and + * you don't know the PIN.) */ - public static final String BOOL_CARRIER_VOLTE_PROVISIONED = "bool_carrier_volte_provisioned"; + public static final String + BOOL_SIM_NETWORK_UNLOCK_ALLOW_DISMISS = "bool_sim_network_unlock_allow_dismiss"; + + /** Flag indicating if the phone is a world phone */ + public static final String BOOL_WORLD_PHONE = "bool_world_phone"; /** - * Flag specifying whether VoLTE TTY is supported. + * If true, enable vibration (haptic feedback) for key presses in the EmergencyDialer activity. + * The pattern is set on a per-platform basis using config_virtualKeyVibePattern. To be + * consistent with the regular Dialer, this value should agree with the corresponding values + * from config.xml under apps/Contacts. */ - public static final String BOOL_CARRIER_VOLTE_TTY_SUPPORTED - = "bool_carrier_volte_tty_supported"; + public static final String + BOOL_ENABLE_DIALER_KEY_VIBRATION = "bool_enable_dialer_key_vibration"; + + /** Flag indicating if dtmf tone type is enabled */ + public static final String BOOL_DTMF_TYPE_ENABLED = "bool_dtmf_type_enabled"; + + /** Flag indicating if auto retry is enabled */ + public static final String BOOL_AUTO_RETRY_ENABLED = "bool_auto_retry_enabled"; /** - * Show APN Settings for some CDMA carriers. + * Determine whether we want to play local DTMF tones in a call, or just let the radio/BP handle + * playing of the tones. */ - public static final String BOOL_SHOW_APN_SETTING_CDMA = "bool_show_apn_setting_cdma"; + public static final String BOOL_ALLOW_LOCAL_DTMF_TONES = "bool_allow_local_dtmf_tones"; + + /** + * If true, show an onscreen "Dial" button in the dialer. In practice this is used on all + * platforms, even the ones with hard SEND/END keys, but for maximum flexibility it's controlled + * by a flag here (which can be overridden on a per-product basis.) + */ + public static final String BOOL_SHOW_ONSCREEN_DIAL_BUTTON = "bool_show_onscreen_dial_button"; + + /** Determines if device implements a noise suppression device for in call audio. */ + public static final String + BOOL_HAS_IN_CALL_NOISE_SUPPRESSION = "bool_has_in_call_noise_suppression"; /** - * Control whether users can edit APNs in Settings. + * Determines if the current device should allow emergency numbers to be logged in the Call Log. + * (Some carriers require that emergency calls *not* be logged, presumably to avoid the risk of + * accidental redialing from the call log UI. This is a good idea, so the default here is + * false.) + * <p> + * TODO: on the other hand, it might still be useful to have some record of the emergency calls + * you've made, or to be able to look up the exact date/time of an emergency call. So perhaps we + * <b>should</b> log those calls, but instead fix the call log to disable the "call" button for + * emergency numbers. */ + public static final String + BOOL_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG = "bool_allow_emergency_numbers_in_call_log"; + + /** If true, removes the Voice Privacy option from Call Settings */ + public static final String BOOL_VOICE_PRIVACY_DISABLE = "bool_voice_privacy_disable"; + + /** Control whether users can reach the carrier portions of Cellular Network Settings. */ + public static final String + BOOL_HIDE_CARRIER_NETWORK_SETTINGS = "bool_hide_carrier_network_settings"; + + /** Control whether users can edit APNs in Settings. */ public static final String BOOL_APN_EXPAND = "bool_apn_expand"; + /** Control whether users can choose a network operator. */ + public static final String BOOL_OPERATOR_SELECTION_EXPAND = "bool_operator_selection_expand"; + + /** Used in Cellular Network Settings for preferred network type. */ + public static final String BOOL_PREFER_2G = "bool_prefer_2g"; + + /** Show cdma auto network mode in (glabal) roaming */ + public static final String BOOL_SHOW_CDMA = "bool_show_cdma"; + + /** CDMA activation goes through HFA */ + public static final String BOOL_USE_HFA_FOR_PROVISIONING = "bool_use_hfa_for_provisioning"; + + /** + * CDMA activation goes through OTASP. + * <p> + * TODO: This should be combined with config_use_hfa_for_provisioning and implemented as an enum + * (NONE, HFA, OTASP). + */ + public static final String BOOL_USE_OTASP_FOR_PROVISIONING = "bool_use_otasp_for_provisioning"; + + /** Display carrier settings menu if true */ + public static final String BOOL_CARRIER_SETTINGS_ENABLE = "bool_carrier_settings_enable"; + + /** Does not display additional call seting for IMS phone based on GSM Phone */ + public static final String BOOL_ADDITIONAL_CALL_SETTING = "bool_additional_call_setting"; + + /** Show APN Settings for some CDMA carriers */ + public static final String BOOL_SHOW_APN_SETTING_CDMA = "bool_show_apn_setting_cdma"; + + /** After a CDMA conference call is merged, the swap button should be displayed. */ + public static final String BOOL_SUPPORT_SWAP_AFTER_MERGE = "bool_support_swap_after_merge"; + + /** + * Determine whether the voicemail notification is persistent in the notification bar. If true, + * the voicemail notifications cannot be dismissed from the notification bar. + */ + public static final String + BOOL_VOICEMAIL_NOTIFICATION_PERSISTENT = "bool_voicemail_notification_persistent"; + + /** For IMS video over LTE calls, determines whether video pause signalling is supported. */ + public static final String + BOOL_SUPPORT_PAUSE_IMS_VIDEO_CALLS = "bool_support_pause_ims_video_calls"; + + /** + * Disables dialing "*228" (OTASP provisioning) on CDMA carriers where it is not supported or is + * potentially harmful by locking the SIM to 3G. + */ + public static final String + BOOL_DISABLE_CDMA_ACTIVATION_CODE = "bool_disable_cdma_activation_code"; + + /** + * Flag specifying whether VoLTE should be available for carrier, independent of carrier + * provisioning. If false: hard disabled. If true: then depends on carrier provisioning, + * availability, etc. + */ + public static final String BOOL_CARRIER_VOLTE_AVAILABLE = "bool_carrier_volte_available"; + + /** Flag specifying whether VoLTE availability is based on provisioning. */ + public static final String BOOL_CARRIER_VOLTE_PROVISIONED = "bool_carrier_volte_provisioned"; + + /** Flag specifying whether VoLTE TTY is supported. */ + public static final String BOOL_CARRIER_VOLTE_TTY_SUPPORTED + = "bool_carrier_volte_tty_supported"; + /** * If Voice Radio Technology is RIL_RADIO_TECHNOLOGY_LTE:14 or RIL_RADIO_TECHNOLOGY_UNKNOWN:0 * this is the value that should be used instead. A configuration value of @@ -86,9 +200,9 @@ public class CarrierConfigManager { /* The following 3 fields are related to carrier visual voicemail. */ /** - * The carrier number MO sms messages are sent to. + * The carrier number MO sms messages are sent to. * - * @hide + * @hide */ public static final String STRING_VVM_DESTINATION_NUMBER = "string_vvm_destination_number"; @@ -122,17 +236,38 @@ public class CarrierConfigManager { static { sDefaults = new Bundle(); + sDefaults.putBoolean(BOOL_ADDITIONAL_CALL_SETTING, true); + sDefaults.putBoolean(BOOL_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG, false); + sDefaults.putBoolean(BOOL_ALLOW_LOCAL_DTMF_TONES, true); + sDefaults.putBoolean(BOOL_APN_EXPAND, true); + sDefaults.putBoolean(BOOL_AUTO_RETRY_ENABLED, false); + sDefaults.putBoolean(BOOL_CARRIER_SETTINGS_ENABLE, false); sDefaults.putBoolean(BOOL_CARRIER_VOLTE_AVAILABLE, false); sDefaults.putBoolean(BOOL_CARRIER_VOLTE_PROVISIONED, false); sDefaults.putBoolean(BOOL_CARRIER_VOLTE_TTY_SUPPORTED, true); + sDefaults.putBoolean(BOOL_DISABLE_CDMA_ACTIVATION_CODE, false); + sDefaults.putBoolean(BOOL_DTMF_TYPE_ENABLED, false); + sDefaults.putBoolean(BOOL_ENABLE_DIALER_KEY_VIBRATION, true); + sDefaults.putBoolean(BOOL_HAS_IN_CALL_NOISE_SUPPRESSION, false); + sDefaults.putBoolean(BOOL_HIDE_CARRIER_NETWORK_SETTINGS, false); + sDefaults.putBoolean(BOOL_IGNORE_SIM_NETWORK_LOCKED_EVENTS, false); + sDefaults.putBoolean(BOOL_OPERATOR_SELECTION_EXPAND, true); + sDefaults.putBoolean(BOOL_PREFER_2G, true); sDefaults.putBoolean(BOOL_SHOW_APN_SETTING_CDMA, false); - sDefaults.putBoolean(BOOL_APN_EXPAND, true); - + sDefaults.putBoolean(BOOL_SHOW_CDMA, false); + sDefaults.putBoolean(BOOL_SHOW_ONSCREEN_DIAL_BUTTON, true); + sDefaults.putBoolean(BOOL_SIM_NETWORK_UNLOCK_ALLOW_DISMISS, true); + sDefaults.putBoolean(BOOL_SUPPORT_PAUSE_IMS_VIDEO_CALLS, true); + sDefaults.putBoolean(BOOL_SUPPORT_SWAP_AFTER_MERGE, true); + sDefaults.putBoolean(BOOL_USE_HFA_FOR_PROVISIONING, false); + sDefaults.putBoolean(BOOL_USE_OTASP_FOR_PROVISIONING, false); + sDefaults.putBoolean(BOOL_VOICEMAIL_NOTIFICATION_PERSISTENT, false); + sDefaults.putBoolean(BOOL_VOICE_PRIVACY_DISABLE, false); + sDefaults.putBoolean(BOOL_WORLD_PHONE, false); sDefaults.putInt(INT_VOLTE_REPLACEMENT_RAT, 0); - + sDefaults.putInt(INT_VVM_PORT_NUMBER, 0); sDefaults.putString(STRING_VVM_DESTINATION_NUMBER, ""); sDefaults.putString(STRING_VVM_TYPE, ""); - sDefaults.putInt(INT_VVM_PORT_NUMBER, 0); } /** @@ -190,10 +325,11 @@ public class CarrierConfigManager { /** * Request the carrier config loader to update the cofig for phoneId. - * - * Depending on simState, the config may be cleared or loaded from config app. - * This is only used by SubscriptionInfoUpdater. - * + * <p> + * Depending on simState, the config may be cleared or loaded from config app. This is only used + * by SubscriptionInfoUpdater. + * </p> + * * @hide */ @SystemApi diff --git a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java index 322b853c6585..30d204f21179 100644 --- a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java @@ -52,6 +52,11 @@ public class ServiceManagerPermissionTests extends TestCase { public boolean checkPermission(java.lang.String permission, int pid, int uid) { return true; } + + @Override + public String[] getPackagesForUid(int uid) { + return new String[0]; + } }; ServiceManagerNative.asInterface(BinderInternal.getContextObject()) .setPermissionController(pc); |