Merge "Notification: Fix bug with sliding action list" into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index 70ea1c5..3bd607b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -299,13 +299,13 @@
field public static final int backgroundTint = 16843883; // 0x101046b
field public static final int backgroundTintMode = 16843884; // 0x101046c
field public static final int backupAgent = 16843391; // 0x101027f
- field public static final int backupInForeground = 16844059; // 0x101051b
+ field public static final int backupInForeground = 16844058; // 0x101051a
field public static final int banner = 16843762; // 0x10103f2
field public static final int baseline = 16843548; // 0x101031c
field public static final int baselineAlignBottom = 16843042; // 0x1010122
field public static final int baselineAligned = 16843046; // 0x1010126
field public static final int baselineAlignedChildIndex = 16843047; // 0x1010127
- field public static final int bitmap = 16844055; // 0x1010517
+ field public static final int bitmap = 16844054; // 0x1010516
field public static final int borderlessButtonStyle = 16843563; // 0x101032b
field public static final int bottom = 16843184; // 0x10101b0
field public static final int bottomBright = 16842957; // 0x10100cd
@@ -324,7 +324,7 @@
field public static final int buttonBarNeutralButtonStyle = 16843914; // 0x101048a
field public static final int buttonBarPositiveButtonStyle = 16843913; // 0x1010489
field public static final int buttonBarStyle = 16843566; // 0x101032e
- field public static final int buttonGravity = 16844031; // 0x10104ff
+ field public static final int buttonGravity = 16844030; // 0x10104fe
field public static final int buttonStyle = 16842824; // 0x1010048
field public static final int buttonStyleInset = 16842826; // 0x101004a
field public static final int buttonStyleSmall = 16842825; // 0x1010049
@@ -335,9 +335,9 @@
field public static final int calendarTextColor = 16843931; // 0x101049b
field public static final int calendarViewShown = 16843596; // 0x101034c
field public static final int calendarViewStyle = 16843613; // 0x101035d
- field public static final int canControlMagnification = 16844040; // 0x1010508
- field public static final int canPerformGestures = 16844046; // 0x101050e
- field public static final int canRecord = 16844061; // 0x101051d
+ field public static final int canControlMagnification = 16844039; // 0x1010507
+ field public static final int canPerformGestures = 16844045; // 0x101050d
+ field public static final int canRecord = 16844060; // 0x101051c
field public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
field public static final int canRequestFilterKeyEvents = 16843737; // 0x10103d9
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
@@ -377,7 +377,7 @@
field public static final int codes = 16843330; // 0x1010242
field public static final int collapseColumns = 16843083; // 0x101014b
field public static final int collapseContentDescription = 16843984; // 0x10104d0
- field public static final int collapseIcon = 16844032; // 0x1010500
+ field public static final int collapseIcon = 16844031; // 0x10104ff
field public static final int color = 16843173; // 0x10101a5
field public static final int colorAccent = 16843829; // 0x1010435
field public static final int colorActivatedHighlight = 16843664; // 0x1010390
@@ -414,18 +414,18 @@
field public static final int contentAuthority = 16843408; // 0x1010290
field public static final int contentDescription = 16843379; // 0x1010273
field public static final int contentInsetEnd = 16843860; // 0x1010454
- field public static final int contentInsetEndWithActions = 16844070; // 0x1010526
+ field public static final int contentInsetEndWithActions = 16844067; // 0x1010523
field public static final int contentInsetLeft = 16843861; // 0x1010455
field public static final int contentInsetRight = 16843862; // 0x1010456
field public static final int contentInsetStart = 16843859; // 0x1010453
- field public static final int contentInsetStartWithNavigation = 16844069; // 0x1010525
+ field public static final int contentInsetStartWithNavigation = 16844066; // 0x1010522
field public static final int contextClickable = 16844007; // 0x10104e7
- field public static final int contextPopupMenuStyle = 16844034; // 0x1010502
+ field public static final int contextPopupMenuStyle = 16844033; // 0x1010501
field public static final int controlX1 = 16843772; // 0x10103fc
field public static final int controlX2 = 16843774; // 0x10103fe
field public static final int controlY1 = 16843773; // 0x10103fd
field public static final int controlY2 = 16843775; // 0x10103ff
- field public static final int countDown = 16844060; // 0x101051c
+ field public static final int countDown = 16844059; // 0x101051b
field public static final int country = 16843962; // 0x10104ba
field public static final int cropToPadding = 16843043; // 0x1010123
field public static final int cursorVisible = 16843090; // 0x1010152
@@ -443,7 +443,7 @@
field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
field public static final int debuggable = 16842767; // 0x101000f
field public static final int defaultHeight = 16844021; // 0x10104f5
- field public static final int defaultToDeviceProtectedStorage = 16844037; // 0x1010505
+ field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
field public static final int defaultValue = 16843245; // 0x10101ed
field public static final int defaultWidth = 16844020; // 0x10104f4
field public static final int delay = 16843212; // 0x10101cc
@@ -463,7 +463,7 @@
field public static final int dialogTheme = 16843528; // 0x1010308
field public static final int dialogTitle = 16843250; // 0x10101f2
field public static final int digits = 16843110; // 0x1010166
- field public static final int directBootAware = 16844038; // 0x1010506
+ field public static final int directBootAware = 16844037; // 0x1010505
field public static final int direction = 16843217; // 0x10101d1
field public static final deprecated int directionDescriptions = 16843681; // 0x10103a1
field public static final int directionPriority = 16843218; // 0x10101d2
@@ -511,12 +511,12 @@
field public static final int elevation = 16843840; // 0x1010440
field public static final int ellipsize = 16842923; // 0x10100ab
field public static final int ems = 16843096; // 0x1010158
- field public static final int enableVrMode = 16844072; // 0x1010528
+ field public static final int enableVrMode = 16844069; // 0x1010525
field public static final int enabled = 16842766; // 0x101000e
field public static final int end = 16843996; // 0x10104dc
field public static final int endColor = 16843166; // 0x101019e
- field public static final int endX = 16844051; // 0x1010513
- field public static final int endY = 16844052; // 0x1010514
+ field public static final int endX = 16844050; // 0x1010512
+ field public static final int endY = 16844051; // 0x1010513
field public static final deprecated int endYear = 16843133; // 0x101017d
field public static final int enterFadeDuration = 16843532; // 0x101030c
field public static final int entries = 16842930; // 0x10100b2
@@ -536,7 +536,7 @@
field public static final int expandableListViewStyle = 16842863; // 0x101006f
field public static final int expandableListViewWhiteStyle = 16843446; // 0x10102b6
field public static final int exported = 16842768; // 0x1010010
- field public static final int externalService = 16844047; // 0x101050f
+ field public static final int externalService = 16844046; // 0x101050e
field public static final int extraTension = 16843371; // 0x101026b
field public static final int extractNativeLibs = 16844010; // 0x10104ea
field public static final int factor = 16843219; // 0x10101d3
@@ -561,7 +561,7 @@
field public static final int fillBefore = 16843196; // 0x10101bc
field public static final int fillColor = 16843780; // 0x1010404
field public static final int fillEnabled = 16843343; // 0x101024f
- field public static final int fillType = 16844064; // 0x1010520
+ field public static final int fillType = 16844062; // 0x101051e
field public static final int fillViewport = 16843130; // 0x101017a
field public static final int filter = 16843035; // 0x101011b
field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -577,7 +577,7 @@
field public static final int fontFamily = 16843692; // 0x10103ac
field public static final int fontFeatureSettings = 16843959; // 0x10104b7
field public static final int footerDividersEnabled = 16843311; // 0x101022f
- field public static final int forceHasOverlappingRendering = 16844068; // 0x1010524
+ field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
field public static final int foreground = 16843017; // 0x1010109
field public static final int foregroundGravity = 16843264; // 0x1010200
field public static final int foregroundTint = 16843885; // 0x101046d
@@ -654,8 +654,8 @@
field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
field public static final int horizontalSpacing = 16843028; // 0x1010114
field public static final int host = 16842792; // 0x1010028
- field public static final int hotSpotX = 16844056; // 0x1010518
- field public static final int hotSpotY = 16844057; // 0x1010519
+ field public static final int hotSpotX = 16844055; // 0x1010517
+ field public static final int hotSpotY = 16844056; // 0x1010518
field public static final int hyphenationFrequency = 16843998; // 0x10104de
field public static final int icon = 16842754; // 0x1010002
field public static final int iconPreview = 16843337; // 0x1010249
@@ -742,7 +742,7 @@
field public static final int label = 16842753; // 0x1010001
field public static final int labelFor = 16843718; // 0x10103c6
field public static final int labelTextSize = 16843317; // 0x1010235
- field public static final int languageTag = 16844041; // 0x1010509
+ field public static final int languageTag = 16844040; // 0x1010508
field public static final int largeHeap = 16843610; // 0x101035a
field public static final int largeScreens = 16843398; // 0x1010286
field public static final int largestWidthLimitDp = 16843622; // 0x1010366
@@ -800,7 +800,7 @@
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
field public static final int letterSpacing = 16843958; // 0x10104b6
- field public static final int level = 16844033; // 0x1010501
+ field public static final int level = 16844032; // 0x1010500
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
field public static final int lines = 16843092; // 0x1010154
@@ -833,7 +833,7 @@
field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
field public static final int matchOrder = 16843855; // 0x101044f
field public static final int max = 16843062; // 0x1010136
- field public static final int maxButtonHeight = 16844030; // 0x10104fe
+ field public static final int maxButtonHeight = 16844029; // 0x10104fd
field public static final int maxDate = 16843584; // 0x1010340
field public static final int maxEms = 16843095; // 0x1010157
field public static final int maxHeight = 16843040; // 0x1010120
@@ -876,26 +876,25 @@
field public static final int navigationMode = 16843471; // 0x10102cf
field public static final int negativeButtonText = 16843254; // 0x10101f6
field public static final int nestedScrollingEnabled = 16843830; // 0x1010436
- field public static final int networkSecurityConfig = 16844074; // 0x101052a
+ field public static final int networkSecurityConfig = 16844071; // 0x1010527
field public static final int nextFocusDown = 16842980; // 0x10100e4
field public static final int nextFocusForward = 16843580; // 0x101033c
field public static final int nextFocusLeft = 16842977; // 0x10100e1
field public static final int nextFocusRight = 16842978; // 0x10100e2
field public static final int nextFocusUp = 16842979; // 0x10100e3
- field public static final int nfcAntennaPositionDrawable = 16844063; // 0x101051f
field public static final int noHistory = 16843309; // 0x101022d
field public static final int normalScreens = 16843397; // 0x1010285
field public static final int notificationTimeout = 16843651; // 0x1010383
field public static final int numColumns = 16843032; // 0x1010118
field public static final int numStars = 16843076; // 0x1010144
- field public static final int numberPickerStyle = 16844071; // 0x1010527
+ field public static final int numberPickerStyle = 16844068; // 0x1010524
field public static final int numbersBackgroundColor = 16843938; // 0x10104a2
field public static final int numbersInnerTextColor = 16844001; // 0x10104e1
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
field public static final int numericShortcut = 16843236; // 0x10101e4
- field public static final int offset = 16844053; // 0x1010515
+ field public static final int offset = 16844052; // 0x1010514
field public static final int onClick = 16843375; // 0x101026f
field public static final int oneshot = 16843159; // 0x1010197
field public static final int opacity = 16843550; // 0x101031e
@@ -942,13 +941,13 @@
field public static final deprecated int phoneNumber = 16843111; // 0x1010167
field public static final int pivotX = 16843189; // 0x10101b5
field public static final int pivotY = 16843190; // 0x10101b6
- field public static final int pointerIcon = 16844042; // 0x101050a
+ field public static final int pointerIcon = 16844041; // 0x1010509
field public static final int popupAnimationStyle = 16843465; // 0x10102c9
field public static final int popupBackground = 16843126; // 0x1010176
field public static final int popupCharacters = 16843332; // 0x1010244
field public static final int popupElevation = 16843916; // 0x101048c
- field public static final int popupEnterTransition = 16844065; // 0x1010521
- field public static final int popupExitTransition = 16844066; // 0x1010522
+ field public static final int popupEnterTransition = 16844063; // 0x101051f
+ field public static final int popupExitTransition = 16844064; // 0x1010520
field public static final int popupKeyboard = 16843331; // 0x1010243
field public static final int popupLayout = 16843323; // 0x101023b
field public static final int popupMenuStyle = 16843520; // 0x1010300
@@ -957,7 +956,7 @@
field public static final int port = 16842793; // 0x1010029
field public static final int positiveButtonText = 16843253; // 0x10101f5
field public static final int preferenceCategoryStyle = 16842892; // 0x101008c
- field public static final int preferenceFragmentStyle = 16844039; // 0x1010507
+ field public static final int preferenceFragmentStyle = 16844038; // 0x1010506
field public static final int preferenceInformationStyle = 16842893; // 0x101008d
field public static final int preferenceLayoutChild = 16842900; // 0x1010094
field public static final int preferenceScreenStyle = 16842891; // 0x101008b
@@ -1025,7 +1024,7 @@
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 = 16844023; // 0x10104f7
+ field public static final int resizeableActivity = 16844022; // 0x10104f6
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
@@ -1145,8 +1144,8 @@
field public static final int startColor = 16843165; // 0x101019d
field public static final int startDelay = 16843746; // 0x10103e2
field public static final int startOffset = 16843198; // 0x10101be
- field public static final int startX = 16844049; // 0x1010511
- field public static final int startY = 16844050; // 0x1010512
+ field public static final int startX = 16844048; // 0x1010510
+ field public static final int startY = 16844049; // 0x1010511
field public static final deprecated int startYear = 16843132; // 0x101017c
field public static final int stateListAnimator = 16843848; // 0x1010448
field public static final int stateNotNeeded = 16842774; // 0x1010016
@@ -1203,8 +1202,8 @@
field public static final int summaryOn = 16843247; // 0x10101ef
field public static final int supportsAssist = 16844016; // 0x10104f0
field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
- field public static final int supportsLocalInteraction = 16844048; // 0x1010510
- field public static final int supportsPictureInPicture = 16844024; // 0x10104f8
+ field public static final int supportsLocalInteraction = 16844047; // 0x101050f
+ field public static final int supportsPictureInPicture = 16844023; // 0x10104f7
field public static final int supportsRtl = 16843695; // 0x10103af
field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
field public static final int supportsUploading = 16843419; // 0x101029b
@@ -1253,7 +1252,7 @@
field public static final int textAppearanceListItemSmall = 16843679; // 0x101039f
field public static final int textAppearanceMedium = 16842817; // 0x1010041
field public static final int textAppearanceMediumInverse = 16842820; // 0x1010044
- field public static final int textAppearancePopupMenuHeader = 16844035; // 0x1010503
+ field public static final int textAppearancePopupMenuHeader = 16844034; // 0x1010502
field public static final int textAppearanceSearchResultSubtitle = 16843424; // 0x10102a0
field public static final int textAppearanceSearchResultTitle = 16843425; // 0x10102a1
field public static final int textAppearanceSmall = 16842818; // 0x1010042
@@ -1311,9 +1310,9 @@
field public static final int thumbTint = 16843889; // 0x1010471
field public static final int thumbTintMode = 16843890; // 0x1010472
field public static final int thumbnail = 16843429; // 0x10102a5
- field public static final int tickMark = 16844043; // 0x101050b
- field public static final int tickMarkTint = 16844044; // 0x101050c
- field public static final int tickMarkTintMode = 16844045; // 0x101050d
+ field public static final int tickMark = 16844042; // 0x101050a
+ field public static final int tickMarkTint = 16844043; // 0x101050b
+ field public static final int tickMarkTintMode = 16844044; // 0x101050c
field public static final int tileMode = 16843265; // 0x1010201
field public static final int tileModeX = 16843895; // 0x1010477
field public static final int tileModeY = 16843896; // 0x1010478
@@ -1325,11 +1324,11 @@
field public static final int tintMode = 16843771; // 0x10103fb
field public static final int title = 16843233; // 0x10101e1
field public static final int titleCondensed = 16843234; // 0x10101e2
- field public static final int titleMargin = 16844025; // 0x10104f9
- field public static final int titleMarginBottom = 16844029; // 0x10104fd
- field public static final int titleMarginEnd = 16844027; // 0x10104fb
- field public static final int titleMarginStart = 16844026; // 0x10104fa
- field public static final int titleMarginTop = 16844028; // 0x10104fc
+ field public static final int titleMargin = 16844024; // 0x10104f8
+ field public static final int titleMarginBottom = 16844028; // 0x10104fc
+ field public static final int titleMarginEnd = 16844026; // 0x10104fa
+ field public static final int titleMarginStart = 16844025; // 0x10104f9
+ field public static final int titleMarginTop = 16844027; // 0x10104fb
field public static final int titleTextAppearance = 16843822; // 0x101042e
field public static final int titleTextColor = 16844003; // 0x10104e3
field public static final int titleTextStyle = 16843512; // 0x10102f8
@@ -1368,7 +1367,7 @@
field public static final int trimPathEnd = 16843785; // 0x1010409
field public static final int trimPathOffset = 16843786; // 0x101040a
field public static final int trimPathStart = 16843784; // 0x1010408
- field public static final int tunerCount = 16844062; // 0x101051e
+ field public static final int tunerCount = 16844061; // 0x101051d
field public static final int type = 16843169; // 0x10101a1
field public static final int typeface = 16842902; // 0x1010096
field public static final int uiOptions = 16843672; // 0x1010398
@@ -1376,7 +1375,7 @@
field public static final deprecated int unfocusedMonthDateColor = 16843588; // 0x1010344
field public static final int unselectedAlpha = 16843278; // 0x101020e
field public static final int updatePeriodMillis = 16843344; // 0x1010250
- field public static final int use32bitAbi = 16844054; // 0x1010516
+ field public static final int use32bitAbi = 16844053; // 0x1010515
field public static final int useDefaultMargins = 16843641; // 0x1010379
field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
field public static final int useLevel = 16843167; // 0x101019f
@@ -1388,7 +1387,7 @@
field public static final int valueType = 16843488; // 0x10102e0
field public static final int variablePadding = 16843157; // 0x1010195
field public static final int vendor = 16843751; // 0x10103e7
- field public static final int version = 16844058; // 0x101051a
+ field public static final int version = 16844057; // 0x1010519
field public static final int versionCode = 16843291; // 0x101021b
field public static final int versionName = 16843292; // 0x101021c
field public static final int verticalCorrection = 16843322; // 0x101023a
@@ -1432,7 +1431,7 @@
field public static final int windowAllowReturnTransitionOverlap = 16843835; // 0x101043b
field public static final int windowAnimationStyle = 16842926; // 0x10100ae
field public static final int windowBackground = 16842836; // 0x1010054
- field public static final int windowBackgroundFallback = 16844036; // 0x1010504
+ field public static final int windowBackgroundFallback = 16844035; // 0x1010503
field public static final int windowClipToOutline = 16843947; // 0x10104ab
field public static final int windowCloseOnTouchOutside = 16843611; // 0x101035b
field public static final int windowContentOverlay = 16842841; // 0x1010059
@@ -2024,6 +2023,8 @@
field public static final int TextAppearance_Material_Widget_ActionMode_Title = 16974355; // 0x1030213
field public static final int TextAppearance_Material_Widget_ActionMode_Title_Inverse = 16974356; // 0x1030214
field public static final int TextAppearance_Material_Widget_Button = 16974357; // 0x1030215
+ field public static final int TextAppearance_Material_Widget_Button_Borderless_Colored = 16974559; // 0x10302df
+ field public static final int TextAppearance_Material_Widget_Button_Colored = 16974558; // 0x10302de
field public static final int TextAppearance_Material_Widget_Button_Inverse = 16974548; // 0x10302d4
field public static final int TextAppearance_Material_Widget_DropDownHint = 16974358; // 0x1030216
field public static final int TextAppearance_Material_Widget_DropDownItem = 16974359; // 0x1030217
@@ -6455,7 +6456,7 @@
public class NetworkStatsManager {
method public android.app.usage.NetworkStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
- method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int);
+ method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int) throws java.lang.SecurityException;
method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
@@ -23624,7 +23625,6 @@
method public boolean isConnected();
method public boolean isConnectedOrConnecting();
method public boolean isFailover();
- method public boolean isMetered();
method public boolean isRoaming();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
@@ -28267,7 +28267,7 @@
field public static final int LOLLIPOP = 21; // 0x15
field public static final int LOLLIPOP_MR1 = 22; // 0x16
field public static final int M = 23; // 0x17
- field public static final int N = 10000; // 0x2710
+ field public static final int N = 24; // 0x18
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -34401,7 +34401,7 @@
field public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
field public static final int RECEIVE_OPTIONS_DEFAULT = 0; // 0x0
field public static final int RECEIVE_OPTIONS_DROP = 1; // 0x1
- field public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 2; // 0x2
+ field public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE = 2; // 0x2
field public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; // 0x1
field public static final int SEND_STATUS_ERROR = 2; // 0x2
field public static final int SEND_STATUS_OK = 0; // 0x0
@@ -34569,7 +34569,7 @@
package android.service.notification {
- public class Condition implements android.os.Parcelable {
+ public final class Condition implements android.os.Parcelable {
ctor public Condition(android.net.Uri, java.lang.String, int);
ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
ctor public Condition(android.os.Parcel);
@@ -34606,7 +34606,7 @@
method public void onRequestConditions(int);
method public abstract void onSubscribe(android.net.Uri);
method public abstract void onUnsubscribe(android.net.Uri);
- field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
+ field public static final java.lang.String EXTRA_RULE_ID = "android.service.notification.extra.RULE_ID";
field public static final java.lang.String META_DATA_CONFIGURATION_ACTIVITY = "android.service.zen.automatic.configurationActivity";
field public static final java.lang.String META_DATA_RULE_INSTANCE_LIMIT = "android.service.zen.automatic.ruleInstanceLimit";
field public static final java.lang.String META_DATA_RULE_TYPE = "android.service.zen.automatic.ruleType";
@@ -36608,11 +36608,9 @@
package android.telephony {
public class CarrierConfigManager {
- method public android.os.PersistableBundle getConfig(int);
method public android.os.PersistableBundle getConfig();
- method public deprecated android.os.PersistableBundle getConfigForSubId(int);
- method public void notifyConfigChanged(int);
- method public deprecated void notifyConfigChangedForSubId(int);
+ method public android.os.PersistableBundle getConfigForSubId(int);
+ method public void notifyConfigChangedForSubId(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 KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool";
field public static final java.lang.String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool";
@@ -37204,69 +37202,47 @@
public class TelephonyManager {
method public boolean canChangeDtmfToneLength();
+ method public android.telephony.TelephonyManager createForSubscriptionId(int);
method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
method public int getCallState();
- method public int getCallState(int);
method public android.telephony.CellLocation getCellLocation();
method public int getDataActivity();
- method public int getDataNetworkType(int);
+ method public int getDataNetworkType();
method public int getDataState();
method public java.lang.String getDeviceId();
method public java.lang.String getDeviceId(int);
method public java.lang.String getDeviceSoftwareVersion();
method public java.lang.String getGroupIdLevel1();
- method public java.lang.String getGroupIdLevel1(int);
method public java.lang.String getIccAuthentication(int, int, java.lang.String);
- method public java.lang.String getIccAuthentication(int, int, int, java.lang.String);
- method public java.lang.String getLine1AlphaTag(int);
method public java.lang.String getLine1Number();
- method public java.lang.String getLine1Number(int);
method public java.lang.String getMmsUAProfUrl();
method public java.lang.String getMmsUserAgent();
method public deprecated java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
method public java.lang.String getNetworkCountryIso();
- method public java.lang.String getNetworkCountryIso(int);
method public java.lang.String getNetworkOperator();
- method public java.lang.String getNetworkOperator(int);
method public java.lang.String getNetworkOperatorName();
- method public java.lang.String getNetworkOperatorName(int);
method public int getNetworkType();
- method public int getNetworkType(int);
method public int getPhoneCount();
method public int getPhoneType();
method public java.lang.String getSimCountryIso();
- method public java.lang.String getSimCountryIso(int);
method public java.lang.String getSimOperator();
- method public java.lang.String getSimOperator(int);
method public java.lang.String getSimOperatorName();
- method public java.lang.String getSimOperatorName(int);
method public java.lang.String getSimSerialNumber();
- method public java.lang.String getSimSerialNumber(int);
method public int getSimState();
method public java.lang.String getSubscriberId();
- method public java.lang.String getSubscriberId(int);
method public java.lang.String getVoiceMailAlphaTag();
- method public java.lang.String getVoiceMailAlphaTag(int);
method public java.lang.String getVoiceMailNumber();
- method public java.lang.String getVoiceMailNumber(int);
- method public int getVoiceNetworkType(int);
+ method public int getVoiceNetworkType();
method public android.net.Uri getVoicemailRingtoneUri(android.telecom.PhoneAccountHandle);
method public boolean hasCarrierPrivileges();
- method public boolean hasCarrierPrivileges(int);
method public boolean hasIccCard();
method public boolean iccCloseLogicalChannel(int);
- method public boolean iccCloseLogicalChannel(int, int);
method public byte[] iccExchangeSimIO(int, int, int, int, int, java.lang.String);
- method public byte[] iccExchangeSimIO(int, int, int, int, int, int, java.lang.String);
method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
- method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(int, java.lang.String);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
- method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
- method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, int, java.lang.String);
method public boolean isHearingAidCompatibilitySupported();
method public boolean isNetworkRoaming();
- method public boolean isNetworkRoaming(int);
method public boolean isSmsCapable();
method public boolean isTtyModeSupported();
method public boolean isVoiceCapable();
@@ -37274,15 +37250,10 @@
method public boolean isWorldPhone();
method public void listen(android.telephony.PhoneStateListener, int);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
- method public java.lang.String sendEnvelopeWithStatus(int, java.lang.String);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
- method public boolean setLine1NumberForDisplay(int, java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
- method public boolean setOperatorBrandOverride(int, java.lang.String);
method public boolean setPreferredNetworkTypeToGlobal();
- method public boolean setPreferredNetworkTypeToGlobal(int);
method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
- method public boolean setVoiceMailNumber(int, java.lang.String, java.lang.String);
field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
@@ -37763,7 +37734,7 @@
ctor public MockApplication();
}
- public deprecated class MockContentProvider extends android.content.ContentProvider {
+ public class MockContentProvider extends android.content.ContentProvider {
ctor protected MockContentProvider();
ctor public MockContentProvider(android.content.Context);
ctor public MockContentProvider(android.content.Context, java.lang.String, java.lang.String, android.content.pm.PathPermission[]);
@@ -37775,13 +37746,13 @@
method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
}
- public deprecated class MockContentResolver extends android.content.ContentResolver {
+ public class MockContentResolver extends android.content.ContentResolver {
ctor public MockContentResolver();
ctor public MockContentResolver(android.content.Context);
method public void addProvider(java.lang.String, android.content.ContentProvider);
}
- public deprecated class MockContext extends android.content.Context {
+ public class MockContext extends android.content.Context {
ctor public MockContext();
method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
method public int checkCallingOrSelfPermission(java.lang.String);
@@ -42388,7 +42359,6 @@
method public boolean hasNestedScrollingParent();
method public boolean hasOnClickListeners();
method public boolean hasOverlappingRendering();
- method public boolean hasPointerCapture();
method public boolean hasTransientState();
method public boolean hasWindowFocus();
method public static android.view.View inflate(android.content.Context, int, android.view.ViewGroup);
@@ -42501,6 +42471,7 @@
method protected boolean overScrollBy(int, int, int, int, int, int, int, int, boolean);
method public boolean performAccessibilityAction(int, android.os.Bundle);
method public boolean performClick();
+ method public boolean performContextClick(float, float);
method public boolean performContextClick();
method public boolean performHapticFeedback(int);
method public boolean performHapticFeedback(int, int);
@@ -42518,7 +42489,6 @@
method public void postOnAnimation(java.lang.Runnable);
method public void postOnAnimationDelayed(java.lang.Runnable, long);
method public void refreshDrawableState();
- method public void releasePointerCapture();
method public boolean removeCallbacks(java.lang.Runnable);
method public void removeOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
method public void removeOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
@@ -42529,7 +42499,6 @@
method public boolean requestFocus(int, android.graphics.Rect);
method public final boolean requestFocusFromTouch();
method public void requestLayout();
- method public void requestPointerCapture();
method public boolean requestRectangleOnScreen(android.graphics.Rect);
method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
method public final void requestUnbufferedDispatch(android.view.MotionEvent);
diff --git a/api/removed.txt b/api/removed.txt
index 73a439c..8119834 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -1,17 +1,3 @@
-package android {
-
- public static final class R.attr {
- field public static final int minimalHeight = 16844067; // 0x1010523
- field public static final int minimalWidth = 16844022; // 0x10104f6
- }
-
- public static final class R.styleable {
- field public static final int AndroidManifestLayout_minimalHeight = 6; // 0x6
- field public static final int AndroidManifestLayout_minimalWidth = 5; // 0x5
- }
-
-}
-
package android.app {
public class Notification implements android.os.Parcelable {
@@ -31,37 +17,6 @@
}
-package android.app.usage {
-
- public class DataUsagePolicy {
- field public final int networkType;
- field public final java.lang.String[] subscriberIds;
- field public final long thresholdInBytes;
- field public final int[] uids;
- }
-
- public static class DataUsagePolicy.Builder {
- ctor public DataUsagePolicy.Builder();
- method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String);
- method public android.app.usage.DataUsagePolicy.Builder addUid(int);
- method public android.app.usage.DataUsagePolicy build();
- method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int);
- method public android.app.usage.DataUsagePolicy.Builder setThreshold(long);
- }
-
- public class NetworkStatsManager {
- method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler);
- method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.UsageCallback, android.os.Handler);
- method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback);
- }
-
- public static abstract class NetworkStatsManager.DataUsageCallback {
- ctor public NetworkStatsManager.DataUsageCallback();
- method public deprecated void onLimitReached();
- }
-
-}
-
package android.content {
public abstract class Context {
@@ -196,10 +151,6 @@
ctor public AudioFormat();
}
- public static abstract class AudioManager.AudioRecordingCallback {
- method public deprecated void onRecordingConfigChanged(android.media.AudioRecordingConfiguration[]);
- }
-
}
package android.media.tv {
@@ -503,11 +454,6 @@
package com.android.internal {
- public static final class R.attr {
- field public static final int minimalHeight = 16844067; // 0x1010523
- field public static final int minimalWidth = 16844022; // 0x10104f6
- }
-
public static final class R.styleable {
field public static final int AndroidManifestLayout_minimalHeight = 6; // 0x6
field public static final int AndroidManifestLayout_minimalWidth = 5; // 0x5
diff --git a/api/system-current.txt b/api/system-current.txt
index a6f612d..3a2f29b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -405,13 +405,13 @@
field public static final int backgroundTint = 16843883; // 0x101046b
field public static final int backgroundTintMode = 16843884; // 0x101046c
field public static final int backupAgent = 16843391; // 0x101027f
- field public static final int backupInForeground = 16844059; // 0x101051b
+ field public static final int backupInForeground = 16844058; // 0x101051a
field public static final int banner = 16843762; // 0x10103f2
field public static final int baseline = 16843548; // 0x101031c
field public static final int baselineAlignBottom = 16843042; // 0x1010122
field public static final int baselineAligned = 16843046; // 0x1010126
field public static final int baselineAlignedChildIndex = 16843047; // 0x1010127
- field public static final int bitmap = 16844055; // 0x1010517
+ field public static final int bitmap = 16844054; // 0x1010516
field public static final int borderlessButtonStyle = 16843563; // 0x101032b
field public static final int bottom = 16843184; // 0x10101b0
field public static final int bottomBright = 16842957; // 0x10100cd
@@ -430,7 +430,7 @@
field public static final int buttonBarNeutralButtonStyle = 16843914; // 0x101048a
field public static final int buttonBarPositiveButtonStyle = 16843913; // 0x1010489
field public static final int buttonBarStyle = 16843566; // 0x101032e
- field public static final int buttonGravity = 16844031; // 0x10104ff
+ field public static final int buttonGravity = 16844030; // 0x10104fe
field public static final int buttonStyle = 16842824; // 0x1010048
field public static final int buttonStyleInset = 16842826; // 0x101004a
field public static final int buttonStyleSmall = 16842825; // 0x1010049
@@ -441,9 +441,9 @@
field public static final int calendarTextColor = 16843931; // 0x101049b
field public static final int calendarViewShown = 16843596; // 0x101034c
field public static final int calendarViewStyle = 16843613; // 0x101035d
- field public static final int canControlMagnification = 16844040; // 0x1010508
- field public static final int canPerformGestures = 16844046; // 0x101050e
- field public static final int canRecord = 16844061; // 0x101051d
+ field public static final int canControlMagnification = 16844039; // 0x1010507
+ field public static final int canPerformGestures = 16844045; // 0x101050d
+ field public static final int canRecord = 16844060; // 0x101051c
field public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
field public static final int canRequestFilterKeyEvents = 16843737; // 0x10103d9
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
@@ -483,7 +483,7 @@
field public static final int codes = 16843330; // 0x1010242
field public static final int collapseColumns = 16843083; // 0x101014b
field public static final int collapseContentDescription = 16843984; // 0x10104d0
- field public static final int collapseIcon = 16844032; // 0x1010500
+ field public static final int collapseIcon = 16844031; // 0x10104ff
field public static final int color = 16843173; // 0x10101a5
field public static final int colorAccent = 16843829; // 0x1010435
field public static final int colorActivatedHighlight = 16843664; // 0x1010390
@@ -520,18 +520,18 @@
field public static final int contentAuthority = 16843408; // 0x1010290
field public static final int contentDescription = 16843379; // 0x1010273
field public static final int contentInsetEnd = 16843860; // 0x1010454
- field public static final int contentInsetEndWithActions = 16844070; // 0x1010526
+ field public static final int contentInsetEndWithActions = 16844067; // 0x1010523
field public static final int contentInsetLeft = 16843861; // 0x1010455
field public static final int contentInsetRight = 16843862; // 0x1010456
field public static final int contentInsetStart = 16843859; // 0x1010453
- field public static final int contentInsetStartWithNavigation = 16844069; // 0x1010525
+ field public static final int contentInsetStartWithNavigation = 16844066; // 0x1010522
field public static final int contextClickable = 16844007; // 0x10104e7
- field public static final int contextPopupMenuStyle = 16844034; // 0x1010502
+ field public static final int contextPopupMenuStyle = 16844033; // 0x1010501
field public static final int controlX1 = 16843772; // 0x10103fc
field public static final int controlX2 = 16843774; // 0x10103fe
field public static final int controlY1 = 16843773; // 0x10103fd
field public static final int controlY2 = 16843775; // 0x10103ff
- field public static final int countDown = 16844060; // 0x101051c
+ field public static final int countDown = 16844059; // 0x101051b
field public static final int country = 16843962; // 0x10104ba
field public static final int cropToPadding = 16843043; // 0x1010123
field public static final int cursorVisible = 16843090; // 0x1010152
@@ -549,7 +549,7 @@
field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
field public static final int debuggable = 16842767; // 0x101000f
field public static final int defaultHeight = 16844021; // 0x10104f5
- field public static final int defaultToDeviceProtectedStorage = 16844037; // 0x1010505
+ field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
field public static final int defaultValue = 16843245; // 0x10101ed
field public static final int defaultWidth = 16844020; // 0x10104f4
field public static final int delay = 16843212; // 0x10101cc
@@ -569,7 +569,7 @@
field public static final int dialogTheme = 16843528; // 0x1010308
field public static final int dialogTitle = 16843250; // 0x10101f2
field public static final int digits = 16843110; // 0x1010166
- field public static final int directBootAware = 16844038; // 0x1010506
+ field public static final int directBootAware = 16844037; // 0x1010505
field public static final int direction = 16843217; // 0x10101d1
field public static final deprecated int directionDescriptions = 16843681; // 0x10103a1
field public static final int directionPriority = 16843218; // 0x10101d2
@@ -617,12 +617,12 @@
field public static final int elevation = 16843840; // 0x1010440
field public static final int ellipsize = 16842923; // 0x10100ab
field public static final int ems = 16843096; // 0x1010158
- field public static final int enableVrMode = 16844072; // 0x1010528
+ field public static final int enableVrMode = 16844069; // 0x1010525
field public static final int enabled = 16842766; // 0x101000e
field public static final int end = 16843996; // 0x10104dc
field public static final int endColor = 16843166; // 0x101019e
- field public static final int endX = 16844051; // 0x1010513
- field public static final int endY = 16844052; // 0x1010514
+ field public static final int endX = 16844050; // 0x1010512
+ field public static final int endY = 16844051; // 0x1010513
field public static final deprecated int endYear = 16843133; // 0x101017d
field public static final int enterFadeDuration = 16843532; // 0x101030c
field public static final int entries = 16842930; // 0x10100b2
@@ -642,7 +642,7 @@
field public static final int expandableListViewStyle = 16842863; // 0x101006f
field public static final int expandableListViewWhiteStyle = 16843446; // 0x10102b6
field public static final int exported = 16842768; // 0x1010010
- field public static final int externalService = 16844047; // 0x101050f
+ field public static final int externalService = 16844046; // 0x101050e
field public static final int extraTension = 16843371; // 0x101026b
field public static final int extractNativeLibs = 16844010; // 0x10104ea
field public static final int factor = 16843219; // 0x10101d3
@@ -667,7 +667,7 @@
field public static final int fillBefore = 16843196; // 0x10101bc
field public static final int fillColor = 16843780; // 0x1010404
field public static final int fillEnabled = 16843343; // 0x101024f
- field public static final int fillType = 16844064; // 0x1010520
+ field public static final int fillType = 16844062; // 0x101051e
field public static final int fillViewport = 16843130; // 0x101017a
field public static final int filter = 16843035; // 0x101011b
field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -683,7 +683,7 @@
field public static final int fontFamily = 16843692; // 0x10103ac
field public static final int fontFeatureSettings = 16843959; // 0x10104b7
field public static final int footerDividersEnabled = 16843311; // 0x101022f
- field public static final int forceHasOverlappingRendering = 16844068; // 0x1010524
+ field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
field public static final int foreground = 16843017; // 0x1010109
field public static final int foregroundGravity = 16843264; // 0x1010200
field public static final int foregroundTint = 16843885; // 0x101046d
@@ -760,8 +760,8 @@
field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
field public static final int horizontalSpacing = 16843028; // 0x1010114
field public static final int host = 16842792; // 0x1010028
- field public static final int hotSpotX = 16844056; // 0x1010518
- field public static final int hotSpotY = 16844057; // 0x1010519
+ field public static final int hotSpotX = 16844055; // 0x1010517
+ field public static final int hotSpotY = 16844056; // 0x1010518
field public static final int hyphenationFrequency = 16843998; // 0x10104de
field public static final int icon = 16842754; // 0x1010002
field public static final int iconPreview = 16843337; // 0x1010249
@@ -848,7 +848,7 @@
field public static final int label = 16842753; // 0x1010001
field public static final int labelFor = 16843718; // 0x10103c6
field public static final int labelTextSize = 16843317; // 0x1010235
- field public static final int languageTag = 16844041; // 0x1010509
+ field public static final int languageTag = 16844040; // 0x1010508
field public static final int largeHeap = 16843610; // 0x101035a
field public static final int largeScreens = 16843398; // 0x1010286
field public static final int largestWidthLimitDp = 16843622; // 0x1010366
@@ -906,7 +906,7 @@
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
field public static final int letterSpacing = 16843958; // 0x10104b6
- field public static final int level = 16844033; // 0x1010501
+ field public static final int level = 16844032; // 0x1010500
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
field public static final int lines = 16843092; // 0x1010154
@@ -939,7 +939,7 @@
field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
field public static final int matchOrder = 16843855; // 0x101044f
field public static final int max = 16843062; // 0x1010136
- field public static final int maxButtonHeight = 16844030; // 0x10104fe
+ field public static final int maxButtonHeight = 16844029; // 0x10104fd
field public static final int maxDate = 16843584; // 0x1010340
field public static final int maxEms = 16843095; // 0x1010157
field public static final int maxHeight = 16843040; // 0x1010120
@@ -982,26 +982,25 @@
field public static final int navigationMode = 16843471; // 0x10102cf
field public static final int negativeButtonText = 16843254; // 0x10101f6
field public static final int nestedScrollingEnabled = 16843830; // 0x1010436
- field public static final int networkSecurityConfig = 16844074; // 0x101052a
+ field public static final int networkSecurityConfig = 16844071; // 0x1010527
field public static final int nextFocusDown = 16842980; // 0x10100e4
field public static final int nextFocusForward = 16843580; // 0x101033c
field public static final int nextFocusLeft = 16842977; // 0x10100e1
field public static final int nextFocusRight = 16842978; // 0x10100e2
field public static final int nextFocusUp = 16842979; // 0x10100e3
- field public static final int nfcAntennaPositionDrawable = 16844063; // 0x101051f
field public static final int noHistory = 16843309; // 0x101022d
field public static final int normalScreens = 16843397; // 0x1010285
field public static final int notificationTimeout = 16843651; // 0x1010383
field public static final int numColumns = 16843032; // 0x1010118
field public static final int numStars = 16843076; // 0x1010144
- field public static final int numberPickerStyle = 16844071; // 0x1010527
+ field public static final int numberPickerStyle = 16844068; // 0x1010524
field public static final int numbersBackgroundColor = 16843938; // 0x10104a2
field public static final int numbersInnerTextColor = 16844001; // 0x10104e1
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
field public static final int numericShortcut = 16843236; // 0x10101e4
- field public static final int offset = 16844053; // 0x1010515
+ field public static final int offset = 16844052; // 0x1010514
field public static final int onClick = 16843375; // 0x101026f
field public static final int oneshot = 16843159; // 0x1010197
field public static final int opacity = 16843550; // 0x101031e
@@ -1048,13 +1047,13 @@
field public static final deprecated int phoneNumber = 16843111; // 0x1010167
field public static final int pivotX = 16843189; // 0x10101b5
field public static final int pivotY = 16843190; // 0x10101b6
- field public static final int pointerIcon = 16844042; // 0x101050a
+ field public static final int pointerIcon = 16844041; // 0x1010509
field public static final int popupAnimationStyle = 16843465; // 0x10102c9
field public static final int popupBackground = 16843126; // 0x1010176
field public static final int popupCharacters = 16843332; // 0x1010244
field public static final int popupElevation = 16843916; // 0x101048c
- field public static final int popupEnterTransition = 16844065; // 0x1010521
- field public static final int popupExitTransition = 16844066; // 0x1010522
+ field public static final int popupEnterTransition = 16844063; // 0x101051f
+ field public static final int popupExitTransition = 16844064; // 0x1010520
field public static final int popupKeyboard = 16843331; // 0x1010243
field public static final int popupLayout = 16843323; // 0x101023b
field public static final int popupMenuStyle = 16843520; // 0x1010300
@@ -1063,7 +1062,7 @@
field public static final int port = 16842793; // 0x1010029
field public static final int positiveButtonText = 16843253; // 0x10101f5
field public static final int preferenceCategoryStyle = 16842892; // 0x101008c
- field public static final int preferenceFragmentStyle = 16844039; // 0x1010507
+ field public static final int preferenceFragmentStyle = 16844038; // 0x1010506
field public static final int preferenceInformationStyle = 16842893; // 0x101008d
field public static final int preferenceLayoutChild = 16842900; // 0x1010094
field public static final int preferenceScreenStyle = 16842891; // 0x101008b
@@ -1131,7 +1130,7 @@
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 = 16844023; // 0x10104f7
+ field public static final int resizeableActivity = 16844022; // 0x10104f6
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
@@ -1255,8 +1254,8 @@
field public static final int startColor = 16843165; // 0x101019d
field public static final int startDelay = 16843746; // 0x10103e2
field public static final int startOffset = 16843198; // 0x10101be
- field public static final int startX = 16844049; // 0x1010511
- field public static final int startY = 16844050; // 0x1010512
+ field public static final int startX = 16844048; // 0x1010510
+ field public static final int startY = 16844049; // 0x1010511
field public static final deprecated int startYear = 16843132; // 0x101017c
field public static final int stateListAnimator = 16843848; // 0x1010448
field public static final int stateNotNeeded = 16842774; // 0x1010016
@@ -1313,8 +1312,8 @@
field public static final int summaryOn = 16843247; // 0x10101ef
field public static final int supportsAssist = 16844016; // 0x10104f0
field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
- field public static final int supportsLocalInteraction = 16844048; // 0x1010510
- field public static final int supportsPictureInPicture = 16844024; // 0x10104f8
+ field public static final int supportsLocalInteraction = 16844047; // 0x101050f
+ field public static final int supportsPictureInPicture = 16844023; // 0x10104f7
field public static final int supportsRtl = 16843695; // 0x10103af
field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
field public static final int supportsUploading = 16843419; // 0x101029b
@@ -1363,7 +1362,7 @@
field public static final int textAppearanceListItemSmall = 16843679; // 0x101039f
field public static final int textAppearanceMedium = 16842817; // 0x1010041
field public static final int textAppearanceMediumInverse = 16842820; // 0x1010044
- field public static final int textAppearancePopupMenuHeader = 16844035; // 0x1010503
+ field public static final int textAppearancePopupMenuHeader = 16844034; // 0x1010502
field public static final int textAppearanceSearchResultSubtitle = 16843424; // 0x10102a0
field public static final int textAppearanceSearchResultTitle = 16843425; // 0x10102a1
field public static final int textAppearanceSmall = 16842818; // 0x1010042
@@ -1421,9 +1420,9 @@
field public static final int thumbTint = 16843889; // 0x1010471
field public static final int thumbTintMode = 16843890; // 0x1010472
field public static final int thumbnail = 16843429; // 0x10102a5
- field public static final int tickMark = 16844043; // 0x101050b
- field public static final int tickMarkTint = 16844044; // 0x101050c
- field public static final int tickMarkTintMode = 16844045; // 0x101050d
+ field public static final int tickMark = 16844042; // 0x101050a
+ field public static final int tickMarkTint = 16844043; // 0x101050b
+ field public static final int tickMarkTintMode = 16844044; // 0x101050c
field public static final int tileMode = 16843265; // 0x1010201
field public static final int tileModeX = 16843895; // 0x1010477
field public static final int tileModeY = 16843896; // 0x1010478
@@ -1435,11 +1434,11 @@
field public static final int tintMode = 16843771; // 0x10103fb
field public static final int title = 16843233; // 0x10101e1
field public static final int titleCondensed = 16843234; // 0x10101e2
- field public static final int titleMargin = 16844025; // 0x10104f9
- field public static final int titleMarginBottom = 16844029; // 0x10104fd
- field public static final int titleMarginEnd = 16844027; // 0x10104fb
- field public static final int titleMarginStart = 16844026; // 0x10104fa
- field public static final int titleMarginTop = 16844028; // 0x10104fc
+ field public static final int titleMargin = 16844024; // 0x10104f8
+ field public static final int titleMarginBottom = 16844028; // 0x10104fc
+ field public static final int titleMarginEnd = 16844026; // 0x10104fa
+ field public static final int titleMarginStart = 16844025; // 0x10104f9
+ field public static final int titleMarginTop = 16844027; // 0x10104fb
field public static final int titleTextAppearance = 16843822; // 0x101042e
field public static final int titleTextColor = 16844003; // 0x10104e3
field public static final int titleTextStyle = 16843512; // 0x10102f8
@@ -1478,7 +1477,7 @@
field public static final int trimPathEnd = 16843785; // 0x1010409
field public static final int trimPathOffset = 16843786; // 0x101040a
field public static final int trimPathStart = 16843784; // 0x1010408
- field public static final int tunerCount = 16844062; // 0x101051e
+ field public static final int tunerCount = 16844061; // 0x101051d
field public static final int type = 16843169; // 0x10101a1
field public static final int typeface = 16842902; // 0x1010096
field public static final int uiOptions = 16843672; // 0x1010398
@@ -1486,7 +1485,7 @@
field public static final deprecated int unfocusedMonthDateColor = 16843588; // 0x1010344
field public static final int unselectedAlpha = 16843278; // 0x101020e
field public static final int updatePeriodMillis = 16843344; // 0x1010250
- field public static final int use32bitAbi = 16844054; // 0x1010516
+ field public static final int use32bitAbi = 16844053; // 0x1010515
field public static final int useDefaultMargins = 16843641; // 0x1010379
field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
field public static final int useLevel = 16843167; // 0x101019f
@@ -1498,7 +1497,7 @@
field public static final int valueType = 16843488; // 0x10102e0
field public static final int variablePadding = 16843157; // 0x1010195
field public static final int vendor = 16843751; // 0x10103e7
- field public static final int version = 16844058; // 0x101051a
+ field public static final int version = 16844057; // 0x1010519
field public static final int versionCode = 16843291; // 0x101021b
field public static final int versionName = 16843292; // 0x101021c
field public static final int verticalCorrection = 16843322; // 0x101023a
@@ -1542,7 +1541,7 @@
field public static final int windowAllowReturnTransitionOverlap = 16843835; // 0x101043b
field public static final int windowAnimationStyle = 16842926; // 0x10100ae
field public static final int windowBackground = 16842836; // 0x1010054
- field public static final int windowBackgroundFallback = 16844036; // 0x1010504
+ field public static final int windowBackgroundFallback = 16844035; // 0x1010503
field public static final int windowClipToOutline = 16843947; // 0x10104ab
field public static final int windowCloseOnTouchOutside = 16843611; // 0x101035b
field public static final int windowContentOverlay = 16842841; // 0x1010059
@@ -2136,6 +2135,8 @@
field public static final int TextAppearance_Material_Widget_ActionMode_Title = 16974355; // 0x1030213
field public static final int TextAppearance_Material_Widget_ActionMode_Title_Inverse = 16974356; // 0x1030214
field public static final int TextAppearance_Material_Widget_Button = 16974357; // 0x1030215
+ field public static final int TextAppearance_Material_Widget_Button_Borderless_Colored = 16974559; // 0x10302df
+ field public static final int TextAppearance_Material_Widget_Button_Colored = 16974558; // 0x10302de
field public static final int TextAppearance_Material_Widget_Button_Inverse = 16974548; // 0x10302d4
field public static final int TextAppearance_Material_Widget_DropDownHint = 16974358; // 0x1030216
field public static final int TextAppearance_Material_Widget_DropDownItem = 16974359; // 0x1030217
@@ -6736,7 +6737,7 @@
public class NetworkStatsManager {
method public android.app.usage.NetworkStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
- method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int);
+ method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int) throws java.lang.SecurityException;
method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
@@ -25446,7 +25447,6 @@
method public boolean isConnected();
method public boolean isConnectedOrConnecting();
method public boolean isFailover();
- method public boolean isMetered();
method public boolean isRoaming();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
@@ -30706,7 +30706,7 @@
field public static final int LOLLIPOP = 21; // 0x15
field public static final int LOLLIPOP_MR1 = 22; // 0x16
field public static final int M = 23; // 0x17
- field public static final int N = 10000; // 0x2710
+ field public static final int N = 24; // 0x18
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -37107,7 +37107,7 @@
field public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
field public static final int RECEIVE_OPTIONS_DEFAULT = 0; // 0x0
field public static final int RECEIVE_OPTIONS_DROP = 1; // 0x1
- field public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 2; // 0x2
+ field public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE = 2; // 0x2
field public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; // 0x1
field public static final int SEND_STATUS_ERROR = 2; // 0x2
field public static final int SEND_STATUS_OK = 0; // 0x0
@@ -37292,7 +37292,7 @@
field public static final java.lang.String NEEDS_AUTOGROUPING_KEY = "autogroup_needed";
}
- public class Condition implements android.os.Parcelable {
+ public final class Condition implements android.os.Parcelable {
ctor public Condition(android.net.Uri, java.lang.String, int);
ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
ctor public Condition(android.os.Parcel);
@@ -37329,7 +37329,7 @@
method public void onRequestConditions(int);
method public abstract void onSubscribe(android.net.Uri);
method public abstract void onUnsubscribe(android.net.Uri);
- field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
+ field public static final java.lang.String EXTRA_RULE_ID = "android.service.notification.extra.RULE_ID";
field public static final java.lang.String META_DATA_CONFIGURATION_ACTIVITY = "android.service.zen.automatic.configurationActivity";
field public static final java.lang.String META_DATA_RULE_INSTANCE_LIMIT = "android.service.zen.automatic.ruleInstanceLimit";
field public static final java.lang.String META_DATA_RULE_TYPE = "android.service.zen.automatic.ruleType";
@@ -39539,12 +39539,10 @@
package android.telephony {
public class CarrierConfigManager {
- method public android.os.PersistableBundle getConfig(int);
method public android.os.PersistableBundle getConfig();
- method public deprecated android.os.PersistableBundle getConfigForSubId(int);
+ method public android.os.PersistableBundle getConfigForSubId(int);
method public static android.os.PersistableBundle getDefaultConfig();
- method public void notifyConfigChanged(int);
- method public deprecated void notifyConfigChangedForSubId(int);
+ method public void notifyConfigChangedForSubId(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 KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool";
@@ -40141,6 +40139,7 @@
method public boolean canChangeDtmfToneLength();
method public int checkCarrierPrivilegesForPackage(java.lang.String);
method public int checkCarrierPrivilegesForPackageAnyPhone(java.lang.String);
+ method public android.telephony.TelephonyManager createForSubscriptionId(int);
method public void dial(java.lang.String);
method public boolean disableDataConnectivity();
method public boolean enableDataConnectivity();
@@ -40148,7 +40147,6 @@
method public boolean endCall();
method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
method public int getCallState();
- method public int getCallState(int);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
method public java.lang.String getCdmaMdn();
@@ -40161,68 +40159,46 @@
method public int getDataActivity();
method public boolean getDataEnabled();
method public boolean getDataEnabled(int);
- method public int getDataNetworkType(int);
+ method public int getDataNetworkType();
method public int getDataState();
method public java.lang.String getDeviceId();
method public java.lang.String getDeviceId(int);
method public java.lang.String getDeviceSoftwareVersion();
method public java.lang.String getGroupIdLevel1();
- method public java.lang.String getGroupIdLevel1(int);
method public java.lang.String getIccAuthentication(int, int, java.lang.String);
- method public java.lang.String getIccAuthentication(int, int, int, java.lang.String);
- method public java.lang.String getLine1AlphaTag(int);
method public java.lang.String getLine1Number();
- method public java.lang.String getLine1Number(int);
method public java.lang.String getMmsUAProfUrl();
method public java.lang.String getMmsUserAgent();
method public deprecated java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
method public java.lang.String getNetworkCountryIso();
- method public java.lang.String getNetworkCountryIso(int);
method public java.lang.String getNetworkOperator();
- method public java.lang.String getNetworkOperator(int);
method public java.lang.String getNetworkOperatorName();
- method public java.lang.String getNetworkOperatorName(int);
method public int getNetworkType();
- method public int getNetworkType(int);
method public int getPhoneCount();
method public int getPhoneType();
method public java.lang.String getSimCountryIso();
- method public java.lang.String getSimCountryIso(int);
method public java.lang.String getSimOperator();
- method public java.lang.String getSimOperator(int);
method public java.lang.String getSimOperatorName();
- method public java.lang.String getSimOperatorName(int);
method public java.lang.String getSimSerialNumber();
- method public java.lang.String getSimSerialNumber(int);
method public int getSimState();
method public java.lang.String getSubscriberId();
- method public java.lang.String getSubscriberId(int);
method public java.lang.String getVoiceMailAlphaTag();
- method public java.lang.String getVoiceMailAlphaTag(int);
method public java.lang.String getVoiceMailNumber();
- method public java.lang.String getVoiceMailNumber(int);
- method public int getVoiceNetworkType(int);
+ method public int getVoiceNetworkType();
method public android.net.Uri getVoicemailRingtoneUri(android.telecom.PhoneAccountHandle);
method public boolean handlePinMmi(java.lang.String);
method public boolean handlePinMmiForSubscriber(int, java.lang.String);
method public boolean hasCarrierPrivileges();
- method public boolean hasCarrierPrivileges(int);
method public boolean hasIccCard();
method public boolean iccCloseLogicalChannel(int);
- method public boolean iccCloseLogicalChannel(int, int);
method public byte[] iccExchangeSimIO(int, int, int, int, int, java.lang.String);
- method public byte[] iccExchangeSimIO(int, int, int, int, int, int, java.lang.String);
method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
- method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(int, java.lang.String);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
- method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
- method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, int, java.lang.String);
method public boolean isDataConnectivityPossible();
method public boolean isHearingAidCompatibilitySupported();
method public boolean isIdle();
method public boolean isNetworkRoaming();
- method public boolean isNetworkRoaming(int);
method public boolean isOffhook();
method public boolean isRadioOn();
method public boolean isRinging();
@@ -40235,19 +40211,14 @@
method public void listen(android.telephony.PhoneStateListener, int);
method public boolean needsOtaServiceProvisioning();
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
- method public java.lang.String sendEnvelopeWithStatus(int, java.lang.String);
method public void setDataEnabled(boolean);
method public void setDataEnabled(int, boolean);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
- method public boolean setLine1NumberForDisplay(int, java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
- method public boolean setOperatorBrandOverride(int, java.lang.String);
method public boolean setPreferredNetworkTypeToGlobal();
- method public boolean setPreferredNetworkTypeToGlobal(int);
method public boolean setRadio(boolean);
method public boolean setRadioPower(boolean);
method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
- method public boolean setVoiceMailNumber(int, java.lang.String, java.lang.String);
method public void silenceRinger();
method public boolean supplyPin(java.lang.String);
method public int[] supplyPinReportResult(java.lang.String);
@@ -40749,7 +40720,7 @@
ctor public MockApplication();
}
- public deprecated class MockContentProvider extends android.content.ContentProvider {
+ public class MockContentProvider extends android.content.ContentProvider {
ctor protected MockContentProvider();
ctor public MockContentProvider(android.content.Context);
ctor public MockContentProvider(android.content.Context, java.lang.String, java.lang.String, android.content.pm.PathPermission[]);
@@ -40761,13 +40732,13 @@
method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
}
- public deprecated class MockContentResolver extends android.content.ContentResolver {
+ public class MockContentResolver extends android.content.ContentResolver {
ctor public MockContentResolver();
ctor public MockContentResolver(android.content.Context);
method public void addProvider(java.lang.String, android.content.ContentProvider);
}
- public deprecated class MockContext extends android.content.Context {
+ public class MockContext extends android.content.Context {
ctor public MockContext();
method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
method public int checkCallingOrSelfPermission(java.lang.String);
@@ -45386,7 +45357,6 @@
method public boolean hasNestedScrollingParent();
method public boolean hasOnClickListeners();
method public boolean hasOverlappingRendering();
- method public boolean hasPointerCapture();
method public boolean hasTransientState();
method public boolean hasWindowFocus();
method public static android.view.View inflate(android.content.Context, int, android.view.ViewGroup);
@@ -45499,6 +45469,7 @@
method protected boolean overScrollBy(int, int, int, int, int, int, int, int, boolean);
method public boolean performAccessibilityAction(int, android.os.Bundle);
method public boolean performClick();
+ method public boolean performContextClick(float, float);
method public boolean performContextClick();
method public boolean performHapticFeedback(int);
method public boolean performHapticFeedback(int, int);
@@ -45516,7 +45487,6 @@
method public void postOnAnimation(java.lang.Runnable);
method public void postOnAnimationDelayed(java.lang.Runnable, long);
method public void refreshDrawableState();
- method public void releasePointerCapture();
method public boolean removeCallbacks(java.lang.Runnable);
method public void removeOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
method public void removeOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
@@ -45527,7 +45497,6 @@
method public boolean requestFocus(int, android.graphics.Rect);
method public final boolean requestFocusFromTouch();
method public void requestLayout();
- method public void requestPointerCapture();
method public boolean requestRectangleOnScreen(android.graphics.Rect);
method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
method public final void requestUnbufferedDispatch(android.view.MotionEvent);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 0a758f8..7f18d6a 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -1,17 +1,3 @@
-package android {
-
- public static final class R.attr {
- field public static final int minimalHeight = 16844067; // 0x1010523
- field public static final int minimalWidth = 16844022; // 0x10104f6
- }
-
- public static final class R.styleable {
- field public static final int AndroidManifestLayout_minimalHeight = 6; // 0x6
- field public static final int AndroidManifestLayout_minimalWidth = 5; // 0x5
- }
-
-}
-
package android.app {
public class Notification implements android.os.Parcelable {
@@ -29,37 +15,6 @@
}
-package android.app.usage {
-
- public class DataUsagePolicy {
- field public final int networkType;
- field public final java.lang.String[] subscriberIds;
- field public final long thresholdInBytes;
- field public final int[] uids;
- }
-
- public static class DataUsagePolicy.Builder {
- ctor public DataUsagePolicy.Builder();
- method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String);
- method public android.app.usage.DataUsagePolicy.Builder addUid(int);
- method public android.app.usage.DataUsagePolicy build();
- method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int);
- method public android.app.usage.DataUsagePolicy.Builder setThreshold(long);
- }
-
- public class NetworkStatsManager {
- method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler);
- method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.UsageCallback, android.os.Handler);
- method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback);
- }
-
- public static abstract class NetworkStatsManager.DataUsageCallback {
- ctor public NetworkStatsManager.DataUsageCallback();
- method public deprecated void onLimitReached();
- }
-
-}
-
package android.content {
public abstract class Context {
@@ -194,10 +149,6 @@
ctor public AudioFormat();
}
- public static abstract class AudioManager.AudioRecordingCallback {
- method public deprecated void onRecordingConfigChanged(android.media.AudioRecordingConfiguration[]);
- }
-
}
package android.media.tv {
@@ -501,11 +452,6 @@
package com.android.internal {
- public static final class R.attr {
- field public static final int minimalHeight = 16844067; // 0x1010523
- field public static final int minimalWidth = 16844022; // 0x10104f6
- }
-
public static final class R.styleable {
field public static final int AndroidManifestLayout_minimalHeight = 6; // 0x6
field public static final int AndroidManifestLayout_minimalWidth = 5; // 0x5
diff --git a/api/test-current.txt b/api/test-current.txt
index 37bc7af..8425e90 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -299,13 +299,13 @@
field public static final int backgroundTint = 16843883; // 0x101046b
field public static final int backgroundTintMode = 16843884; // 0x101046c
field public static final int backupAgent = 16843391; // 0x101027f
- field public static final int backupInForeground = 16844059; // 0x101051b
+ field public static final int backupInForeground = 16844058; // 0x101051a
field public static final int banner = 16843762; // 0x10103f2
field public static final int baseline = 16843548; // 0x101031c
field public static final int baselineAlignBottom = 16843042; // 0x1010122
field public static final int baselineAligned = 16843046; // 0x1010126
field public static final int baselineAlignedChildIndex = 16843047; // 0x1010127
- field public static final int bitmap = 16844055; // 0x1010517
+ field public static final int bitmap = 16844054; // 0x1010516
field public static final int borderlessButtonStyle = 16843563; // 0x101032b
field public static final int bottom = 16843184; // 0x10101b0
field public static final int bottomBright = 16842957; // 0x10100cd
@@ -324,7 +324,7 @@
field public static final int buttonBarNeutralButtonStyle = 16843914; // 0x101048a
field public static final int buttonBarPositiveButtonStyle = 16843913; // 0x1010489
field public static final int buttonBarStyle = 16843566; // 0x101032e
- field public static final int buttonGravity = 16844031; // 0x10104ff
+ field public static final int buttonGravity = 16844030; // 0x10104fe
field public static final int buttonStyle = 16842824; // 0x1010048
field public static final int buttonStyleInset = 16842826; // 0x101004a
field public static final int buttonStyleSmall = 16842825; // 0x1010049
@@ -335,9 +335,9 @@
field public static final int calendarTextColor = 16843931; // 0x101049b
field public static final int calendarViewShown = 16843596; // 0x101034c
field public static final int calendarViewStyle = 16843613; // 0x101035d
- field public static final int canControlMagnification = 16844040; // 0x1010508
- field public static final int canPerformGestures = 16844046; // 0x101050e
- field public static final int canRecord = 16844061; // 0x101051d
+ field public static final int canControlMagnification = 16844039; // 0x1010507
+ field public static final int canPerformGestures = 16844045; // 0x101050d
+ field public static final int canRecord = 16844060; // 0x101051c
field public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
field public static final int canRequestFilterKeyEvents = 16843737; // 0x10103d9
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
@@ -377,7 +377,7 @@
field public static final int codes = 16843330; // 0x1010242
field public static final int collapseColumns = 16843083; // 0x101014b
field public static final int collapseContentDescription = 16843984; // 0x10104d0
- field public static final int collapseIcon = 16844032; // 0x1010500
+ field public static final int collapseIcon = 16844031; // 0x10104ff
field public static final int color = 16843173; // 0x10101a5
field public static final int colorAccent = 16843829; // 0x1010435
field public static final int colorActivatedHighlight = 16843664; // 0x1010390
@@ -414,18 +414,18 @@
field public static final int contentAuthority = 16843408; // 0x1010290
field public static final int contentDescription = 16843379; // 0x1010273
field public static final int contentInsetEnd = 16843860; // 0x1010454
- field public static final int contentInsetEndWithActions = 16844070; // 0x1010526
+ field public static final int contentInsetEndWithActions = 16844067; // 0x1010523
field public static final int contentInsetLeft = 16843861; // 0x1010455
field public static final int contentInsetRight = 16843862; // 0x1010456
field public static final int contentInsetStart = 16843859; // 0x1010453
- field public static final int contentInsetStartWithNavigation = 16844069; // 0x1010525
+ field public static final int contentInsetStartWithNavigation = 16844066; // 0x1010522
field public static final int contextClickable = 16844007; // 0x10104e7
- field public static final int contextPopupMenuStyle = 16844034; // 0x1010502
+ field public static final int contextPopupMenuStyle = 16844033; // 0x1010501
field public static final int controlX1 = 16843772; // 0x10103fc
field public static final int controlX2 = 16843774; // 0x10103fe
field public static final int controlY1 = 16843773; // 0x10103fd
field public static final int controlY2 = 16843775; // 0x10103ff
- field public static final int countDown = 16844060; // 0x101051c
+ field public static final int countDown = 16844059; // 0x101051b
field public static final int country = 16843962; // 0x10104ba
field public static final int cropToPadding = 16843043; // 0x1010123
field public static final int cursorVisible = 16843090; // 0x1010152
@@ -443,7 +443,7 @@
field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
field public static final int debuggable = 16842767; // 0x101000f
field public static final int defaultHeight = 16844021; // 0x10104f5
- field public static final int defaultToDeviceProtectedStorage = 16844037; // 0x1010505
+ field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
field public static final int defaultValue = 16843245; // 0x10101ed
field public static final int defaultWidth = 16844020; // 0x10104f4
field public static final int delay = 16843212; // 0x10101cc
@@ -463,7 +463,7 @@
field public static final int dialogTheme = 16843528; // 0x1010308
field public static final int dialogTitle = 16843250; // 0x10101f2
field public static final int digits = 16843110; // 0x1010166
- field public static final int directBootAware = 16844038; // 0x1010506
+ field public static final int directBootAware = 16844037; // 0x1010505
field public static final int direction = 16843217; // 0x10101d1
field public static final deprecated int directionDescriptions = 16843681; // 0x10103a1
field public static final int directionPriority = 16843218; // 0x10101d2
@@ -511,12 +511,12 @@
field public static final int elevation = 16843840; // 0x1010440
field public static final int ellipsize = 16842923; // 0x10100ab
field public static final int ems = 16843096; // 0x1010158
- field public static final int enableVrMode = 16844072; // 0x1010528
+ field public static final int enableVrMode = 16844069; // 0x1010525
field public static final int enabled = 16842766; // 0x101000e
field public static final int end = 16843996; // 0x10104dc
field public static final int endColor = 16843166; // 0x101019e
- field public static final int endX = 16844051; // 0x1010513
- field public static final int endY = 16844052; // 0x1010514
+ field public static final int endX = 16844050; // 0x1010512
+ field public static final int endY = 16844051; // 0x1010513
field public static final deprecated int endYear = 16843133; // 0x101017d
field public static final int enterFadeDuration = 16843532; // 0x101030c
field public static final int entries = 16842930; // 0x10100b2
@@ -536,7 +536,7 @@
field public static final int expandableListViewStyle = 16842863; // 0x101006f
field public static final int expandableListViewWhiteStyle = 16843446; // 0x10102b6
field public static final int exported = 16842768; // 0x1010010
- field public static final int externalService = 16844047; // 0x101050f
+ field public static final int externalService = 16844046; // 0x101050e
field public static final int extraTension = 16843371; // 0x101026b
field public static final int extractNativeLibs = 16844010; // 0x10104ea
field public static final int factor = 16843219; // 0x10101d3
@@ -561,7 +561,7 @@
field public static final int fillBefore = 16843196; // 0x10101bc
field public static final int fillColor = 16843780; // 0x1010404
field public static final int fillEnabled = 16843343; // 0x101024f
- field public static final int fillType = 16844064; // 0x1010520
+ field public static final int fillType = 16844062; // 0x101051e
field public static final int fillViewport = 16843130; // 0x101017a
field public static final int filter = 16843035; // 0x101011b
field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -577,7 +577,7 @@
field public static final int fontFamily = 16843692; // 0x10103ac
field public static final int fontFeatureSettings = 16843959; // 0x10104b7
field public static final int footerDividersEnabled = 16843311; // 0x101022f
- field public static final int forceHasOverlappingRendering = 16844068; // 0x1010524
+ field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
field public static final int foreground = 16843017; // 0x1010109
field public static final int foregroundGravity = 16843264; // 0x1010200
field public static final int foregroundTint = 16843885; // 0x101046d
@@ -654,8 +654,8 @@
field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
field public static final int horizontalSpacing = 16843028; // 0x1010114
field public static final int host = 16842792; // 0x1010028
- field public static final int hotSpotX = 16844056; // 0x1010518
- field public static final int hotSpotY = 16844057; // 0x1010519
+ field public static final int hotSpotX = 16844055; // 0x1010517
+ field public static final int hotSpotY = 16844056; // 0x1010518
field public static final int hyphenationFrequency = 16843998; // 0x10104de
field public static final int icon = 16842754; // 0x1010002
field public static final int iconPreview = 16843337; // 0x1010249
@@ -742,7 +742,7 @@
field public static final int label = 16842753; // 0x1010001
field public static final int labelFor = 16843718; // 0x10103c6
field public static final int labelTextSize = 16843317; // 0x1010235
- field public static final int languageTag = 16844041; // 0x1010509
+ field public static final int languageTag = 16844040; // 0x1010508
field public static final int largeHeap = 16843610; // 0x101035a
field public static final int largeScreens = 16843398; // 0x1010286
field public static final int largestWidthLimitDp = 16843622; // 0x1010366
@@ -800,7 +800,7 @@
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
field public static final int letterSpacing = 16843958; // 0x10104b6
- field public static final int level = 16844033; // 0x1010501
+ field public static final int level = 16844032; // 0x1010500
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
field public static final int lines = 16843092; // 0x1010154
@@ -833,7 +833,7 @@
field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
field public static final int matchOrder = 16843855; // 0x101044f
field public static final int max = 16843062; // 0x1010136
- field public static final int maxButtonHeight = 16844030; // 0x10104fe
+ field public static final int maxButtonHeight = 16844029; // 0x10104fd
field public static final int maxDate = 16843584; // 0x1010340
field public static final int maxEms = 16843095; // 0x1010157
field public static final int maxHeight = 16843040; // 0x1010120
@@ -876,26 +876,25 @@
field public static final int navigationMode = 16843471; // 0x10102cf
field public static final int negativeButtonText = 16843254; // 0x10101f6
field public static final int nestedScrollingEnabled = 16843830; // 0x1010436
- field public static final int networkSecurityConfig = 16844074; // 0x101052a
+ field public static final int networkSecurityConfig = 16844071; // 0x1010527
field public static final int nextFocusDown = 16842980; // 0x10100e4
field public static final int nextFocusForward = 16843580; // 0x101033c
field public static final int nextFocusLeft = 16842977; // 0x10100e1
field public static final int nextFocusRight = 16842978; // 0x10100e2
field public static final int nextFocusUp = 16842979; // 0x10100e3
- field public static final int nfcAntennaPositionDrawable = 16844063; // 0x101051f
field public static final int noHistory = 16843309; // 0x101022d
field public static final int normalScreens = 16843397; // 0x1010285
field public static final int notificationTimeout = 16843651; // 0x1010383
field public static final int numColumns = 16843032; // 0x1010118
field public static final int numStars = 16843076; // 0x1010144
- field public static final int numberPickerStyle = 16844071; // 0x1010527
+ field public static final int numberPickerStyle = 16844068; // 0x1010524
field public static final int numbersBackgroundColor = 16843938; // 0x10104a2
field public static final int numbersInnerTextColor = 16844001; // 0x10104e1
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
field public static final int numericShortcut = 16843236; // 0x10101e4
- field public static final int offset = 16844053; // 0x1010515
+ field public static final int offset = 16844052; // 0x1010514
field public static final int onClick = 16843375; // 0x101026f
field public static final int oneshot = 16843159; // 0x1010197
field public static final int opacity = 16843550; // 0x101031e
@@ -942,13 +941,13 @@
field public static final deprecated int phoneNumber = 16843111; // 0x1010167
field public static final int pivotX = 16843189; // 0x10101b5
field public static final int pivotY = 16843190; // 0x10101b6
- field public static final int pointerIcon = 16844042; // 0x101050a
+ field public static final int pointerIcon = 16844041; // 0x1010509
field public static final int popupAnimationStyle = 16843465; // 0x10102c9
field public static final int popupBackground = 16843126; // 0x1010176
field public static final int popupCharacters = 16843332; // 0x1010244
field public static final int popupElevation = 16843916; // 0x101048c
- field public static final int popupEnterTransition = 16844065; // 0x1010521
- field public static final int popupExitTransition = 16844066; // 0x1010522
+ field public static final int popupEnterTransition = 16844063; // 0x101051f
+ field public static final int popupExitTransition = 16844064; // 0x1010520
field public static final int popupKeyboard = 16843331; // 0x1010243
field public static final int popupLayout = 16843323; // 0x101023b
field public static final int popupMenuStyle = 16843520; // 0x1010300
@@ -957,7 +956,7 @@
field public static final int port = 16842793; // 0x1010029
field public static final int positiveButtonText = 16843253; // 0x10101f5
field public static final int preferenceCategoryStyle = 16842892; // 0x101008c
- field public static final int preferenceFragmentStyle = 16844039; // 0x1010507
+ field public static final int preferenceFragmentStyle = 16844038; // 0x1010506
field public static final int preferenceInformationStyle = 16842893; // 0x101008d
field public static final int preferenceLayoutChild = 16842900; // 0x1010094
field public static final int preferenceScreenStyle = 16842891; // 0x101008b
@@ -1025,7 +1024,7 @@
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 = 16844023; // 0x10104f7
+ field public static final int resizeableActivity = 16844022; // 0x10104f6
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
@@ -1145,8 +1144,8 @@
field public static final int startColor = 16843165; // 0x101019d
field public static final int startDelay = 16843746; // 0x10103e2
field public static final int startOffset = 16843198; // 0x10101be
- field public static final int startX = 16844049; // 0x1010511
- field public static final int startY = 16844050; // 0x1010512
+ field public static final int startX = 16844048; // 0x1010510
+ field public static final int startY = 16844049; // 0x1010511
field public static final deprecated int startYear = 16843132; // 0x101017c
field public static final int stateListAnimator = 16843848; // 0x1010448
field public static final int stateNotNeeded = 16842774; // 0x1010016
@@ -1203,8 +1202,8 @@
field public static final int summaryOn = 16843247; // 0x10101ef
field public static final int supportsAssist = 16844016; // 0x10104f0
field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
- field public static final int supportsLocalInteraction = 16844048; // 0x1010510
- field public static final int supportsPictureInPicture = 16844024; // 0x10104f8
+ field public static final int supportsLocalInteraction = 16844047; // 0x101050f
+ field public static final int supportsPictureInPicture = 16844023; // 0x10104f7
field public static final int supportsRtl = 16843695; // 0x10103af
field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
field public static final int supportsUploading = 16843419; // 0x101029b
@@ -1253,7 +1252,7 @@
field public static final int textAppearanceListItemSmall = 16843679; // 0x101039f
field public static final int textAppearanceMedium = 16842817; // 0x1010041
field public static final int textAppearanceMediumInverse = 16842820; // 0x1010044
- field public static final int textAppearancePopupMenuHeader = 16844035; // 0x1010503
+ field public static final int textAppearancePopupMenuHeader = 16844034; // 0x1010502
field public static final int textAppearanceSearchResultSubtitle = 16843424; // 0x10102a0
field public static final int textAppearanceSearchResultTitle = 16843425; // 0x10102a1
field public static final int textAppearanceSmall = 16842818; // 0x1010042
@@ -1311,9 +1310,9 @@
field public static final int thumbTint = 16843889; // 0x1010471
field public static final int thumbTintMode = 16843890; // 0x1010472
field public static final int thumbnail = 16843429; // 0x10102a5
- field public static final int tickMark = 16844043; // 0x101050b
- field public static final int tickMarkTint = 16844044; // 0x101050c
- field public static final int tickMarkTintMode = 16844045; // 0x101050d
+ field public static final int tickMark = 16844042; // 0x101050a
+ field public static final int tickMarkTint = 16844043; // 0x101050b
+ field public static final int tickMarkTintMode = 16844044; // 0x101050c
field public static final int tileMode = 16843265; // 0x1010201
field public static final int tileModeX = 16843895; // 0x1010477
field public static final int tileModeY = 16843896; // 0x1010478
@@ -1325,11 +1324,11 @@
field public static final int tintMode = 16843771; // 0x10103fb
field public static final int title = 16843233; // 0x10101e1
field public static final int titleCondensed = 16843234; // 0x10101e2
- field public static final int titleMargin = 16844025; // 0x10104f9
- field public static final int titleMarginBottom = 16844029; // 0x10104fd
- field public static final int titleMarginEnd = 16844027; // 0x10104fb
- field public static final int titleMarginStart = 16844026; // 0x10104fa
- field public static final int titleMarginTop = 16844028; // 0x10104fc
+ field public static final int titleMargin = 16844024; // 0x10104f8
+ field public static final int titleMarginBottom = 16844028; // 0x10104fc
+ field public static final int titleMarginEnd = 16844026; // 0x10104fa
+ field public static final int titleMarginStart = 16844025; // 0x10104f9
+ field public static final int titleMarginTop = 16844027; // 0x10104fb
field public static final int titleTextAppearance = 16843822; // 0x101042e
field public static final int titleTextColor = 16844003; // 0x10104e3
field public static final int titleTextStyle = 16843512; // 0x10102f8
@@ -1368,7 +1367,7 @@
field public static final int trimPathEnd = 16843785; // 0x1010409
field public static final int trimPathOffset = 16843786; // 0x101040a
field public static final int trimPathStart = 16843784; // 0x1010408
- field public static final int tunerCount = 16844062; // 0x101051e
+ field public static final int tunerCount = 16844061; // 0x101051d
field public static final int type = 16843169; // 0x10101a1
field public static final int typeface = 16842902; // 0x1010096
field public static final int uiOptions = 16843672; // 0x1010398
@@ -1376,7 +1375,7 @@
field public static final deprecated int unfocusedMonthDateColor = 16843588; // 0x1010344
field public static final int unselectedAlpha = 16843278; // 0x101020e
field public static final int updatePeriodMillis = 16843344; // 0x1010250
- field public static final int use32bitAbi = 16844054; // 0x1010516
+ field public static final int use32bitAbi = 16844053; // 0x1010515
field public static final int useDefaultMargins = 16843641; // 0x1010379
field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
field public static final int useLevel = 16843167; // 0x101019f
@@ -1388,7 +1387,7 @@
field public static final int valueType = 16843488; // 0x10102e0
field public static final int variablePadding = 16843157; // 0x1010195
field public static final int vendor = 16843751; // 0x10103e7
- field public static final int version = 16844058; // 0x101051a
+ field public static final int version = 16844057; // 0x1010519
field public static final int versionCode = 16843291; // 0x101021b
field public static final int versionName = 16843292; // 0x101021c
field public static final int verticalCorrection = 16843322; // 0x101023a
@@ -1432,7 +1431,7 @@
field public static final int windowAllowReturnTransitionOverlap = 16843835; // 0x101043b
field public static final int windowAnimationStyle = 16842926; // 0x10100ae
field public static final int windowBackground = 16842836; // 0x1010054
- field public static final int windowBackgroundFallback = 16844036; // 0x1010504
+ field public static final int windowBackgroundFallback = 16844035; // 0x1010503
field public static final int windowClipToOutline = 16843947; // 0x10104ab
field public static final int windowCloseOnTouchOutside = 16843611; // 0x101035b
field public static final int windowContentOverlay = 16842841; // 0x1010059
@@ -2024,6 +2023,8 @@
field public static final int TextAppearance_Material_Widget_ActionMode_Title = 16974355; // 0x1030213
field public static final int TextAppearance_Material_Widget_ActionMode_Title_Inverse = 16974356; // 0x1030214
field public static final int TextAppearance_Material_Widget_Button = 16974357; // 0x1030215
+ field public static final int TextAppearance_Material_Widget_Button_Borderless_Colored = 16974559; // 0x10302df
+ field public static final int TextAppearance_Material_Widget_Button_Colored = 16974558; // 0x10302de
field public static final int TextAppearance_Material_Widget_Button_Inverse = 16974548; // 0x10302d4
field public static final int TextAppearance_Material_Widget_DropDownHint = 16974358; // 0x1030216
field public static final int TextAppearance_Material_Widget_DropDownItem = 16974359; // 0x1030217
@@ -6461,7 +6462,7 @@
public class NetworkStatsManager {
method public android.app.usage.NetworkStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
- method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int);
+ method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int) throws java.lang.SecurityException;
method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
@@ -23693,7 +23694,6 @@
method public boolean isConnected();
method public boolean isConnectedOrConnecting();
method public boolean isFailover();
- method public boolean isMetered();
method public boolean isRoaming();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
@@ -28336,7 +28336,7 @@
field public static final int LOLLIPOP = 21; // 0x15
field public static final int LOLLIPOP_MR1 = 22; // 0x16
field public static final int M = 23; // 0x17
- field public static final int N = 10000; // 0x2710
+ field public static final int N = 24; // 0x18
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -34478,7 +34478,7 @@
field public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
field public static final int RECEIVE_OPTIONS_DEFAULT = 0; // 0x0
field public static final int RECEIVE_OPTIONS_DROP = 1; // 0x1
- field public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 2; // 0x2
+ field public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE = 2; // 0x2
field public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; // 0x1
field public static final int SEND_STATUS_ERROR = 2; // 0x2
field public static final int SEND_STATUS_OK = 0; // 0x0
@@ -34646,7 +34646,7 @@
package android.service.notification {
- public class Condition implements android.os.Parcelable {
+ public final class Condition implements android.os.Parcelable {
ctor public Condition(android.net.Uri, java.lang.String, int);
ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
ctor public Condition(android.os.Parcel);
@@ -34683,7 +34683,7 @@
method public void onRequestConditions(int);
method public abstract void onSubscribe(android.net.Uri);
method public abstract void onUnsubscribe(android.net.Uri);
- field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
+ field public static final java.lang.String EXTRA_RULE_ID = "android.service.notification.extra.RULE_ID";
field public static final java.lang.String META_DATA_CONFIGURATION_ACTIVITY = "android.service.zen.automatic.configurationActivity";
field public static final java.lang.String META_DATA_RULE_INSTANCE_LIMIT = "android.service.zen.automatic.ruleInstanceLimit";
field public static final java.lang.String META_DATA_RULE_TYPE = "android.service.zen.automatic.ruleType";
@@ -36685,11 +36685,9 @@
package android.telephony {
public class CarrierConfigManager {
- method public android.os.PersistableBundle getConfig(int);
method public android.os.PersistableBundle getConfig();
- method public deprecated android.os.PersistableBundle getConfigForSubId(int);
- method public void notifyConfigChanged(int);
- method public deprecated void notifyConfigChangedForSubId(int);
+ method public android.os.PersistableBundle getConfigForSubId(int);
+ method public void notifyConfigChangedForSubId(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 KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool";
field public static final java.lang.String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool";
@@ -37281,69 +37279,47 @@
public class TelephonyManager {
method public boolean canChangeDtmfToneLength();
+ method public android.telephony.TelephonyManager createForSubscriptionId(int);
method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
method public int getCallState();
- method public int getCallState(int);
method public android.telephony.CellLocation getCellLocation();
method public int getDataActivity();
- method public int getDataNetworkType(int);
+ method public int getDataNetworkType();
method public int getDataState();
method public java.lang.String getDeviceId();
method public java.lang.String getDeviceId(int);
method public java.lang.String getDeviceSoftwareVersion();
method public java.lang.String getGroupIdLevel1();
- method public java.lang.String getGroupIdLevel1(int);
method public java.lang.String getIccAuthentication(int, int, java.lang.String);
- method public java.lang.String getIccAuthentication(int, int, int, java.lang.String);
- method public java.lang.String getLine1AlphaTag(int);
method public java.lang.String getLine1Number();
- method public java.lang.String getLine1Number(int);
method public java.lang.String getMmsUAProfUrl();
method public java.lang.String getMmsUserAgent();
method public deprecated java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
method public java.lang.String getNetworkCountryIso();
- method public java.lang.String getNetworkCountryIso(int);
method public java.lang.String getNetworkOperator();
- method public java.lang.String getNetworkOperator(int);
method public java.lang.String getNetworkOperatorName();
- method public java.lang.String getNetworkOperatorName(int);
method public int getNetworkType();
- method public int getNetworkType(int);
method public int getPhoneCount();
method public int getPhoneType();
method public java.lang.String getSimCountryIso();
- method public java.lang.String getSimCountryIso(int);
method public java.lang.String getSimOperator();
- method public java.lang.String getSimOperator(int);
method public java.lang.String getSimOperatorName();
- method public java.lang.String getSimOperatorName(int);
method public java.lang.String getSimSerialNumber();
- method public java.lang.String getSimSerialNumber(int);
method public int getSimState();
method public java.lang.String getSubscriberId();
- method public java.lang.String getSubscriberId(int);
method public java.lang.String getVoiceMailAlphaTag();
- method public java.lang.String getVoiceMailAlphaTag(int);
method public java.lang.String getVoiceMailNumber();
- method public java.lang.String getVoiceMailNumber(int);
- method public int getVoiceNetworkType(int);
+ method public int getVoiceNetworkType();
method public android.net.Uri getVoicemailRingtoneUri(android.telecom.PhoneAccountHandle);
method public boolean hasCarrierPrivileges();
- method public boolean hasCarrierPrivileges(int);
method public boolean hasIccCard();
method public boolean iccCloseLogicalChannel(int);
- method public boolean iccCloseLogicalChannel(int, int);
method public byte[] iccExchangeSimIO(int, int, int, int, int, java.lang.String);
- method public byte[] iccExchangeSimIO(int, int, int, int, int, int, java.lang.String);
method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
- method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(int, java.lang.String);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
- method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
- method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, int, java.lang.String);
method public boolean isHearingAidCompatibilitySupported();
method public boolean isNetworkRoaming();
- method public boolean isNetworkRoaming(int);
method public boolean isSmsCapable();
method public boolean isTtyModeSupported();
method public boolean isVoiceCapable();
@@ -37351,15 +37327,10 @@
method public boolean isWorldPhone();
method public void listen(android.telephony.PhoneStateListener, int);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
- method public java.lang.String sendEnvelopeWithStatus(int, java.lang.String);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
- method public boolean setLine1NumberForDisplay(int, java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
- method public boolean setOperatorBrandOverride(int, java.lang.String);
method public boolean setPreferredNetworkTypeToGlobal();
- method public boolean setPreferredNetworkTypeToGlobal(int);
method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
- method public boolean setVoiceMailNumber(int, java.lang.String, java.lang.String);
field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
@@ -37840,7 +37811,7 @@
ctor public MockApplication();
}
- public deprecated class MockContentProvider extends android.content.ContentProvider {
+ public class MockContentProvider extends android.content.ContentProvider {
ctor protected MockContentProvider();
ctor public MockContentProvider(android.content.Context);
ctor public MockContentProvider(android.content.Context, java.lang.String, java.lang.String, android.content.pm.PathPermission[]);
@@ -37852,13 +37823,13 @@
method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
}
- public deprecated class MockContentResolver extends android.content.ContentResolver {
+ public class MockContentResolver extends android.content.ContentResolver {
ctor public MockContentResolver();
ctor public MockContentResolver(android.content.Context);
method public void addProvider(java.lang.String, android.content.ContentProvider);
}
- public deprecated class MockContext extends android.content.Context {
+ public class MockContext extends android.content.Context {
ctor public MockContext();
method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
method public int checkCallingOrSelfPermission(java.lang.String);
@@ -42467,7 +42438,6 @@
method public boolean hasNestedScrollingParent();
method public boolean hasOnClickListeners();
method public boolean hasOverlappingRendering();
- method public boolean hasPointerCapture();
method public boolean hasTransientState();
method public boolean hasWindowFocus();
method public static android.view.View inflate(android.content.Context, int, android.view.ViewGroup);
@@ -42580,6 +42550,7 @@
method protected boolean overScrollBy(int, int, int, int, int, int, int, int, boolean);
method public boolean performAccessibilityAction(int, android.os.Bundle);
method public boolean performClick();
+ method public boolean performContextClick(float, float);
method public boolean performContextClick();
method public boolean performHapticFeedback(int);
method public boolean performHapticFeedback(int, int);
@@ -42597,7 +42568,6 @@
method public void postOnAnimation(java.lang.Runnable);
method public void postOnAnimationDelayed(java.lang.Runnable, long);
method public void refreshDrawableState();
- method public void releasePointerCapture();
method public boolean removeCallbacks(java.lang.Runnable);
method public void removeOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
method public void removeOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
@@ -42608,7 +42578,6 @@
method public boolean requestFocus(int, android.graphics.Rect);
method public final boolean requestFocusFromTouch();
method public void requestLayout();
- method public void requestPointerCapture();
method public boolean requestRectangleOnScreen(android.graphics.Rect);
method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
method public final void requestUnbufferedDispatch(android.view.MotionEvent);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 73a439c..8119834 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -1,17 +1,3 @@
-package android {
-
- public static final class R.attr {
- field public static final int minimalHeight = 16844067; // 0x1010523
- field public static final int minimalWidth = 16844022; // 0x10104f6
- }
-
- public static final class R.styleable {
- field public static final int AndroidManifestLayout_minimalHeight = 6; // 0x6
- field public static final int AndroidManifestLayout_minimalWidth = 5; // 0x5
- }
-
-}
-
package android.app {
public class Notification implements android.os.Parcelable {
@@ -31,37 +17,6 @@
}
-package android.app.usage {
-
- public class DataUsagePolicy {
- field public final int networkType;
- field public final java.lang.String[] subscriberIds;
- field public final long thresholdInBytes;
- field public final int[] uids;
- }
-
- public static class DataUsagePolicy.Builder {
- ctor public DataUsagePolicy.Builder();
- method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String);
- method public android.app.usage.DataUsagePolicy.Builder addUid(int);
- method public android.app.usage.DataUsagePolicy build();
- method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int);
- method public android.app.usage.DataUsagePolicy.Builder setThreshold(long);
- }
-
- public class NetworkStatsManager {
- method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler);
- method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.UsageCallback, android.os.Handler);
- method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback);
- }
-
- public static abstract class NetworkStatsManager.DataUsageCallback {
- ctor public NetworkStatsManager.DataUsageCallback();
- method public deprecated void onLimitReached();
- }
-
-}
-
package android.content {
public abstract class Context {
@@ -196,10 +151,6 @@
ctor public AudioFormat();
}
- public static abstract class AudioManager.AudioRecordingCallback {
- method public deprecated void onRecordingConfigChanged(android.media.AudioRecordingConfiguration[]);
- }
-
}
package android.media.tv {
@@ -503,11 +454,6 @@
package com.android.internal {
- public static final class R.attr {
- field public static final int minimalHeight = 16844067; // 0x1010523
- field public static final int minimalWidth = 16844022; // 0x10104f6
- }
-
public static final class R.styleable {
field public static final int AndroidManifestLayout_minimalHeight = 6; // 0x6
field public static final int AndroidManifestLayout_minimalWidth = 5; // 0x5
diff --git a/cmds/uiautomator/api/current.txt b/cmds/uiautomator/api/current.txt
index 7eeecf5..634ca4d 100644
--- a/cmds/uiautomator/api/current.txt
+++ b/cmds/uiautomator/api/current.txt
@@ -1,6 +1,6 @@
package com.android.uiautomator.core {
- public final class Configurator {
+ public final deprecated class Configurator {
method public long getActionAcknowledgmentTimeout();
method public static com.android.uiautomator.core.Configurator getInstance();
method public long getKeyInjectionDelay();
@@ -14,7 +14,7 @@
method public com.android.uiautomator.core.Configurator setWaitForSelectorTimeout(long);
}
- public class UiCollection extends com.android.uiautomator.core.UiObject {
+ public deprecated class UiCollection extends com.android.uiautomator.core.UiObject {
ctor public UiCollection(com.android.uiautomator.core.UiSelector);
method public com.android.uiautomator.core.UiObject getChildByDescription(com.android.uiautomator.core.UiSelector, java.lang.String) throws com.android.uiautomator.core.UiObjectNotFoundException;
method public com.android.uiautomator.core.UiObject getChildByInstance(com.android.uiautomator.core.UiSelector, int) throws com.android.uiautomator.core.UiObjectNotFoundException;
@@ -22,7 +22,7 @@
method public int getChildCount(com.android.uiautomator.core.UiSelector);
}
- public class UiDevice {
+ public deprecated class UiDevice {
method public void clearLastTraversedText();
method public boolean click(int, int);
method public boolean drag(int, int, int, int, int);
@@ -77,7 +77,7 @@
method public void wakeUp() throws android.os.RemoteException;
}
- public class UiObject {
+ public deprecated class UiObject {
ctor public UiObject(com.android.uiautomator.core.UiSelector);
method public void clearTextField() throws com.android.uiautomator.core.UiObjectNotFoundException;
method public boolean click() throws com.android.uiautomator.core.UiObjectNotFoundException;
@@ -130,13 +130,13 @@
field protected static final long WAIT_FOR_WINDOW_TMEOUT = 5500L; // 0x157cL
}
- public class UiObjectNotFoundException extends java.lang.Exception {
+ public deprecated class UiObjectNotFoundException extends java.lang.Exception {
ctor public UiObjectNotFoundException(java.lang.String);
ctor public UiObjectNotFoundException(java.lang.String, java.lang.Throwable);
ctor public UiObjectNotFoundException(java.lang.Throwable);
}
- public class UiScrollable extends com.android.uiautomator.core.UiCollection {
+ public deprecated class UiScrollable extends com.android.uiautomator.core.UiCollection {
ctor public UiScrollable(com.android.uiautomator.core.UiSelector);
method protected boolean exists(com.android.uiautomator.core.UiSelector);
method public boolean flingBackward() throws com.android.uiautomator.core.UiObjectNotFoundException;
@@ -165,7 +165,7 @@
method public com.android.uiautomator.core.UiScrollable setSwipeDeadZonePercentage(double);
}
- public class UiSelector {
+ public deprecated class UiSelector {
ctor public UiSelector();
method public com.android.uiautomator.core.UiSelector checkable(boolean);
method public com.android.uiautomator.core.UiSelector checked(boolean);
@@ -198,7 +198,7 @@
method public com.android.uiautomator.core.UiSelector textStartsWith(java.lang.String);
}
- public abstract interface UiWatcher {
+ public abstract deprecated interface UiWatcher {
method public abstract boolean checkForCondition();
}
@@ -206,11 +206,11 @@
package com.android.uiautomator.testrunner {
- public abstract interface IAutomationSupport {
+ public abstract deprecated interface IAutomationSupport {
method public abstract void sendStatus(int, android.os.Bundle);
}
- public class UiAutomatorTestCase extends junit.framework.TestCase {
+ public deprecated class UiAutomatorTestCase extends junit.framework.TestCase {
ctor public UiAutomatorTestCase();
method public com.android.uiautomator.testrunner.IAutomationSupport getAutomationSupport();
method public android.os.Bundle getParams();
diff --git a/cmds/uiautomator/cmds/uiautomator/uiautomator b/cmds/uiautomator/cmds/uiautomator/uiautomator
index fe2c735..86a1dba 100755
--- a/cmds/uiautomator/cmds/uiautomator/uiautomator
+++ b/cmds/uiautomator/cmds/uiautomator/uiautomator
@@ -67,6 +67,11 @@
# special case pre-processing for 'runtest' command
if [ "${cmd}" == "runtest" ]; then
+ # Print deprecation warning
+ echo "Warning: This version of UI Automator is deprecated. New tests should be written using"
+ echo "UI Automator 2.0 which is available as part of the Android Testing Support Library."
+ echo "See https://developer.android.com/training/testing/ui-testing/uiautomator-testing.html"
+ echo "for more details."
# first parse the jar paths
while [ true ]; do
if [ -z "${1}" ] && [ -z "${jars}" ]; then
diff --git a/cmds/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/IAutomationSupport.java b/cmds/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/IAutomationSupport.java
index f0c60d2..6d75844 100644
--- a/cmds/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/IAutomationSupport.java
+++ b/cmds/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/IAutomationSupport.java
@@ -22,7 +22,10 @@
* Provides auxiliary support for running test cases
*
* @since API Level 16
+ * @deprecated New tests should be written using UI Automator 2.0 which is available as part of the
+ * Android Testing Support Library.
*/
+@Deprecated
public interface IAutomationSupport {
/**
diff --git a/cmds/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorInstrumentationTestRunner.java b/cmds/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorInstrumentationTestRunner.java
index ae763f2..af42653 100644
--- a/cmds/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorInstrumentationTestRunner.java
+++ b/cmds/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorInstrumentationTestRunner.java
@@ -28,7 +28,10 @@
/**
* Test runner for {@link UiAutomatorTestCase}s. Such tests are executed
* on the device and have access to an applications context.
+ * @deprecated New tests should be written using UI Automator 2.0 which is available as part of the
+ * Android Testing Support Library.
*/
+@Deprecated
public class UiAutomatorInstrumentationTestRunner extends InstrumentationTestRunner {
@Override
diff --git a/cmds/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java b/cmds/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java
index b5f21c9..7c9aede 100644
--- a/cmds/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java
+++ b/cmds/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java
@@ -26,7 +26,10 @@
/**
* UI Automator test case that is executed on the device.
+ * @deprecated New tests should be written using UI Automator 2.0 which is available as part of the
+ * Android Testing Support Library.
*/
+@Deprecated
public class UiAutomatorTestCase extends InstrumentationTestCase {
private Bundle mParams;
diff --git a/cmds/uiautomator/library/Android.mk b/cmds/uiautomator/library/Android.mk
index 62fb0e4..ea77fbc 100644
--- a/cmds/uiautomator/library/Android.mk
+++ b/cmds/uiautomator/library/Android.mk
@@ -67,7 +67,6 @@
# Make sure to run droiddoc first to generate the stub source files.
$(full_classes_compiled_jar) : $(uiautomator_stubs_stamp)
$(built_dex_intermediate) : $(uiautomator_stubs_stamp)
-uiautomator_stubs_jar := $(full_classes_compiled_jar)
###############################################
# API check
@@ -92,7 +91,7 @@
$(uiautomator_internal_removed_api_file), \
$(checkapi_last_error_level_flags), \
cat $(LOCAL_PATH)/apicheck_msg_last.txt, \
- $(uiautomator_stubs_jar), \
+ uiautomator.core, \
$(uiautomator_stubs_stamp)))
checkapi_current_error_level_flags := \
@@ -111,7 +110,7 @@
$(uiautomator_internal_removed_api_file), \
$(checkapi_current_error_level_flags), \
cat $(LOCAL_PATH)/apicheck_msg_current.txt, \
- $(uiautomator_stubs_jar), \
+ uiautomator.core, \
$(uiautomator_stubs_stamp)))
.PHONY: update-uiautomator-api
@@ -128,7 +127,6 @@
uiautomator.core_java_libraries :=
uiautomator_stubs_stamp :=
uiautomator_internal_api_file :=
-uiautomator_stubs_jar :=
uiautomator_api_dir :=
checkapi_last_error_level_flags :=
checkapi_current_error_level_flags :=
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/Configurator.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/Configurator.java
index 249f404..255c49a 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/Configurator.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/Configurator.java
@@ -25,7 +25,10 @@
* tests with the modified parameters, make sure to also restore
* the original parameter values, otherwise this will impact other tests cases.
* @since API Level 18
+ * @deprecated New tests should be written using UI Automator 2.0 which is available as part of the
+ * Android Testing Support Library.
*/
+@Deprecated
public final class Configurator {
private long mWaitForIdleTimeout = 10 * 1000;
private long mWaitForSelector = 10 * 1000;
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiCollection.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiCollection.java
index e15beb2..06bacb0 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiCollection.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiCollection.java
@@ -19,7 +19,10 @@
* Used to enumerate a container's UI elements for the purpose of counting,
* or targeting a sub elements by a child's text or description.
* @since API Level 16
+ * @deprecated New tests should be written using UI Automator 2.0 which is available as part of the
+ * Android Testing Support Library.
*/
+@Deprecated
public class UiCollection extends UiObject {
/**
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java
index a930eb4..b1b432b 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java
@@ -42,7 +42,10 @@
* You can also use this class to simulate user actions on the device,
* such as pressing the d-pad or pressing the Home and Menu buttons.
* @since API Level 16
+ * @deprecated New tests should be written using UI Automator 2.0 which is available as part of the
+ * Android Testing Support Library.
*/
+@Deprecated
public class UiDevice {
private static final String LOG_TAG = UiDevice.class.getSimpleName();
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java
index 2118da8..751bbe8 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java
@@ -31,7 +31,10 @@
* its constructor. Once you create an instance of a UiObject, it can
* be reused for different views that match the selector criteria.
* @since API Level 16
+ * @deprecated New tests should be written using UI Automator 2.0 which is available as part of the
+ * Android Testing Support Library.
*/
+@Deprecated
public class UiObject {
private static final String LOG_TAG = UiObject.class.getSimpleName();
/**
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObjectNotFoundException.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObjectNotFoundException.java
index fc0891b..f3e2698 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObjectNotFoundException.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObjectNotFoundException.java
@@ -20,7 +20,10 @@
* Generated in test runs when a {@link UiSelector} selector could not be matched
* to any UI element displayed.
* @since API Level 16
+ * @deprecated New tests should be written using UI Automator 2.0 which is available as part of the
+ * Android Testing Support Library.
*/
+@Deprecated
public class UiObjectNotFoundException extends Exception {
private static final long serialVersionUID = 1L;
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiScrollable.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiScrollable.java
index a8d20c3..6673dac 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiScrollable.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiScrollable.java
@@ -24,7 +24,10 @@
* for items in scrollable layout elements. This class can be used with
* horizontally or vertically scrollable controls.
* @since API Level 16
+ * @deprecated New tests should be written using UI Automator 2.0 which is available as part of the
+ * Android Testing Support Library.
*/
+@Deprecated
public class UiScrollable extends UiCollection {
private static final String LOG_TAG = UiScrollable.class.getSimpleName();
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiSelector.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiSelector.java
index 482a74d..9ba425e 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiSelector.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiSelector.java
@@ -27,7 +27,10 @@
* information. You can also target an element by its location in a layout
* hierarchy.
* @since API Level 16
+ * @deprecated New tests should be written using UI Automator 2.0 which is available as part of the
+ * Android Testing Support Library.
*/
+@Deprecated
public class UiSelector {
static final int SELECTOR_NIL = 0;
static final int SELECTOR_TEXT = 1;
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiWatcher.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiWatcher.java
index 5403e30..030fb0a 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiWatcher.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiWatcher.java
@@ -22,7 +22,10 @@
* to locate its selector yet. Only during this time, the watchers are invoked to check if there is
* something else unexpected on the screen.
* @since API Level 16
+ * @deprecated New tests should be written using UI Automator 2.0 which is available as part of the
+ * Android Testing Support Library.
*/
+@Deprecated
public interface UiWatcher {
/**
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/IAutomationSupport.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/IAutomationSupport.java
index f0c60d2..6d75844 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/IAutomationSupport.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/IAutomationSupport.java
@@ -22,7 +22,10 @@
* Provides auxiliary support for running test cases
*
* @since API Level 16
+ * @deprecated New tests should be written using UI Automator 2.0 which is available as part of the
+ * Android Testing Support Library.
*/
+@Deprecated
public interface IAutomationSupport {
/**
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java
index e7d961b..3d5476d 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java
@@ -36,7 +36,10 @@
* {@link UiDevice} instance
* {@link Bundle} for command line parameters.
* @since API Level 16
+ * @deprecated New tests should be written using UI Automator 2.0 which is available as part of the
+ * Android Testing Support Library.
*/
+@Deprecated
public class UiAutomatorTestCase extends TestCase {
private static final String DISABLE_IME = "disable_ime";
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 8ff38bb..7841d29 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -465,20 +465,26 @@
/**
* The amount of time, in milliseconds, to delay starting the animation after
- * {@link #start()} is called.
-
+ * {@link #start()} is called. Note that the start delay should always be non-negative. Any
+ * negative start delay will be clamped to 0 on N and above.
+ *
* @param startDelay The amount of the delay, in milliseconds
*/
@Override
public void setStartDelay(long startDelay) {
- if (mStartDelay > 0) {
- mReversible = false;
+ // Clamp start delay to non-negative range.
+ if (startDelay < 0) {
+ Log.w(TAG, "Start delay should always be non-negative");
+ startDelay = 0;
}
long delta = startDelay - mStartDelay;
if (delta == 0) {
return;
}
mStartDelay = startDelay;
+ if (mStartDelay > 0) {
+ mReversible = false;
+ }
if (!mDependencyDirty) {
// Dependency graph already constructed, update all the nodes' start/end time
int size = mNodes.size();
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 0a9b5de..4edf249 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -708,12 +708,18 @@
/**
* The amount of time, in milliseconds, to delay starting the animation after
- * {@link #start()} is called.
-
+ * {@link #start()} is called. Note that the start delay should always be non-negative. Any
+ * negative start delay will be clamped to 0 on N and above.
+ *
* @param startDelay The amount of the delay, in milliseconds
*/
@Override
public void setStartDelay(long startDelay) {
+ // Clamp start delay to non-negative range.
+ if (startDelay < 0) {
+ Log.w(TAG, "Start delay should always be non-negative");
+ startDelay = 0;
+ }
mStartDelay = startDelay;
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 6d405f6..ac5f3ef 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5948,7 +5948,7 @@
* @return true if this is the topmost, non-finishing activity in its task.
*/
private boolean isTopOfTask() {
- if (mToken == null || mWindow == null || !mWindowAdded) {
+ if (mToken == null || mWindow == null) {
return false;
}
try {
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 4b8d9ee..3a70a4c 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.content.ComponentName;
+import android.content.IIntentSender;
import android.os.IBinder;
import android.service.voice.IVoiceInteractionSession;
@@ -144,4 +145,10 @@
* Kill foreground apps from the specified user.
*/
public abstract void killForegroundAppsForUser(int userHandle);
+
+ /**
+ * Sets how long a {@link PendingIntent} can be temporarily whitelist to by bypass restrictions
+ * such as Power Save mode.
+ */
+ public abstract void setPendingIntentWhitelistDuration(IIntentSender target, long duration);
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index cd9a05b..f12c284 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -6966,8 +6966,8 @@
reply.recycle();
}
- public void notifyLockedProfile(@UserIdInt int userId) throws RemoteException
- {
+ @Override
+ public void notifyLockedProfile(@UserIdInt int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -6978,6 +6978,7 @@
reply.recycle();
}
+ @Override
public void startConfirmDeviceCredentialIntent(Intent intent) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -6989,6 +6990,7 @@
reply.recycle();
}
+ @Override
public int sendIntentSender(IIntentSender target, int code, Intent intent, String resolvedType,
IIntentReceiver finishedReceiver, String requiredPermission, Bundle options)
throws RemoteException {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index dff0769..7198146 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -62,6 +62,7 @@
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
+import android.os.LocaleList;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
@@ -130,6 +131,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.TimeZone;
@@ -4684,6 +4686,8 @@
+ config);
mResourcesManager.applyConfigurationToResourcesLocked(config, compat);
+ updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
+ mResourcesManager.getConfiguration().getLocales());
if (mConfiguration == null) {
mConfiguration = new Configuration();
@@ -4989,6 +4993,27 @@
return insInfo.nativeLibraryDir;
}
+ /**
+ * The LocaleList set for the app's resources may have been shuffled so that the preferred
+ * Locale is at position 0. We must find the index of this preferred Locale in the
+ * original LocaleList.
+ */
+ private void updateLocaleListFromAppContext(Context context, LocaleList newLocaleList) {
+ final Locale bestLocale = context.getResources().getConfiguration().getLocales().get(0);
+ final int newLocaleListSize = newLocaleList.size();
+ for (int i = 0; i < newLocaleListSize; i++) {
+ if (bestLocale.equals(newLocaleList.get(i))) {
+ LocaleList.setDefault(newLocaleList, i);
+ return;
+ }
+ }
+
+ // The app may have overridden the LocaleList with its own Locale
+ // (not present in the available list). Push the chosen Locale
+ // to the front of the list.
+ LocaleList.setDefault(new LocaleList(bestLocale, newLocaleList));
+ }
+
private void handleBindApplication(AppBindData data) {
// Register the UI Thread as a sensitive thread to the runtime.
VMRuntime.registerSensitiveThread();
@@ -5047,6 +5072,24 @@
*/
TimeZone.setDefault(null);
+ /*
+ * Set the LocaleList. This may change once we create the App Context.
+ */
+ LocaleList.setDefault(data.config.getLocales());
+
+ synchronized (mResourcesManager) {
+ /*
+ * Update the system configuration since its preloaded and might not
+ * reflect configuration changes. The configuration object passed
+ * in AppBindData can be safely assumed to be up to date
+ */
+ mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
+ mCurDefaultDisplayDpi = data.config.densityDpi;
+
+ // This calls mResourcesManager so keep it within the synchronized block.
+ applyCompatConfiguration(mCurDefaultDisplayDpi);
+ }
+
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
/**
@@ -5174,25 +5217,8 @@
}
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
- synchronized (mResourcesManager) {
- /*
- * Initialize the default locales in this process for the reasons we set the time zone.
- *
- * We do this through ResourcesManager, since we need to do locale negotiation.
- */
- mResourcesManager.setDefaultLocalesLocked(data.config.getLocales());
-
- /*
- * Update the system configuration since its preloaded and might not
- * reflect configuration changes. The configuration object passed
- * in AppBindData can be safely assumed to be up to date
- */
- mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
- mCurDefaultDisplayDpi = data.config.densityDpi;
-
- // This calls mResourcesManager so keep it within the synchronized block.
- applyCompatConfiguration(mCurDefaultDisplayDpi);
- }
+ updateLocaleListFromAppContext(appContext,
+ mResourcesManager.getConfiguration().getLocales());
if (!Process.isIsolated() && !"android".equals(appContext.getPackageName())) {
// This cache location probably points at credential-encrypted
@@ -5895,6 +5921,9 @@
// immediately, because upon returning the view
// hierarchy will be informed about it.
if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
+ updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
+ mResourcesManager.getConfiguration().getLocales());
+
// This actually changed the resources! Tell
// everyone about it.
if (mPendingConfiguration == null ||
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 4a8203b..0cc44e7 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -58,6 +58,7 @@
import android.view.Gravity;
import android.view.NotificationHeaderView;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.RemoteViews;
@@ -3202,11 +3203,14 @@
bindNotificationHeader(contentView);
bindLargeIcon(contentView);
+ boolean showProgress = handleProgressBar(hasProgress, contentView, ex);
if (title != null) {
contentView.setViewVisibility(R.id.title, View.VISIBLE);
contentView.setTextViewText(R.id.title, title);
+ contentView.setViewLayoutWidth(R.id.title, showProgress
+ ? ViewGroup.LayoutParams.WRAP_CONTENT
+ : ViewGroup.LayoutParams.MATCH_PARENT);
}
- boolean showProgress = handleProgressBar(hasProgress, contentView, ex);
if (text != null) {
int textId = showProgress ? com.android.internal.R.id.text_line_1
: com.android.internal.R.id.text;
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index b4e9db8..25a8b66 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -67,10 +67,6 @@
}
};
- private String[] mSystemLocales = null;
- private final HashSet<String> mNonSystemLocales = new HashSet<>();
- private boolean mHasNonSystemLocales = false;
-
/**
* The global compatibility settings.
*/
@@ -479,12 +475,7 @@
*/
private Resources getOrCreateResources(@Nullable IBinder activityToken,
@NonNull ResourcesKey key, @NonNull ClassLoader classLoader) {
- final boolean findSystemLocales;
- final boolean hasNonSystemLocales;
synchronized (this) {
- findSystemLocales = (mSystemLocales == null || mSystemLocales.length == 0);
- hasNonSystemLocales = mHasNonSystemLocales;
-
if (DEBUG) {
Throwable here = new Throwable();
here.fillInStackTrace();
@@ -538,24 +529,7 @@
// If we're here, we didn't find a suitable ResourcesImpl to use, so create one now.
ResourcesImpl resourcesImpl = createResourcesImpl(key);
- final String[] systemLocales = findSystemLocales
- ? AssetManager.getSystem().getLocales() : null;
- final String[] nonSystemLocales = resourcesImpl.getAssets().getNonSystemLocales();
-
- // Avoid checking for non-pseudo-locales if we already know there were some from a previous
- // Resources. The default value (for when hasNonSystemLocales is true) doesn't matter,
- // since mHasNonSystemLocales will also be true, and thus isPseudoLocalesOnly would not be
- // able to affect mHasNonSystemLocales.
- final boolean isPseudoLocalesOnly = hasNonSystemLocales ||
- LocaleList.isPseudoLocalesOnly(nonSystemLocales);
-
synchronized (this) {
- if (mSystemLocales == null || mSystemLocales.length == 0) {
- mSystemLocales = systemLocales;
- }
- mNonSystemLocales.addAll(Arrays.asList(nonSystemLocales));
- mHasNonSystemLocales = mHasNonSystemLocales || !isPseudoLocalesOnly;
-
ResourcesImpl existingResourcesImpl = findResourcesImplForKeyLocked(key);
if (existingResourcesImpl != null) {
if (DEBUG) {
@@ -745,23 +719,6 @@
}
}
- /* package */ void setDefaultLocalesLocked(@NonNull LocaleList locales) {
- if (mSystemLocales == null) {
- throw new RuntimeException("ResourcesManager is not ready to negotiate locales.");
- }
- final int bestLocale;
- if (mHasNonSystemLocales) {
- bestLocale = locales.getFirstMatchIndexWithEnglishSupported(mNonSystemLocales);
- } else {
- // We fallback to system locales if there was no locale specifically supported by the
- // assets. This is to properly support apps that only rely on the shared system assets
- // and don't need assets of their own.
- bestLocale = locales.getFirstMatchIndexWithEnglishSupported(mSystemLocales);
- }
- // set it for Java, this also affects newly created Resources
- LocaleList.setDefault(locales, bestLocale);
- }
-
public final boolean applyConfigurationToResourcesLocked(@NonNull Configuration config,
@Nullable CompatibilityInfo compat) {
try {
@@ -786,30 +743,7 @@
| ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
}
- Configuration localeAdjustedConfig = config;
- final LocaleList configLocales = config.getLocales();
- if (!configLocales.isEmpty()) {
- setDefaultLocalesLocked(configLocales);
- final LocaleList adjustedLocales = LocaleList.getAdjustedDefault();
- if (adjustedLocales
- != configLocales) { // has the same result as .equals() in this case
- // The first locale in the list was not chosen. So we create a modified
- // configuration with the adjusted locales (which moves the chosen locale to the
- // front).
- localeAdjustedConfig = new Configuration();
- localeAdjustedConfig.setTo(config);
- localeAdjustedConfig.setLocales(adjustedLocales);
- // Also adjust the locale list in mResConfiguration, so that the Resources
- // created later would have the same locale list.
- if (!mResConfiguration.getLocales().equals(adjustedLocales)) {
- mResConfiguration.setLocales(adjustedLocales);
- changes |= ActivityInfo.CONFIG_LOCALE;
- }
- }
- }
-
- Resources.updateSystemConfiguration(localeAdjustedConfig, defaultDisplayMetrics,
- compat);
+ Resources.updateSystemConfiguration(config, defaultDisplayMetrics, compat);
ApplicationPackageManager.configurationChanged();
//Slog.i(TAG, "Configuration changed in " + currentPackageName());
@@ -821,7 +755,7 @@
ResourcesImpl r = mResourceImpls.valueAt(i).get();
if (r != null) {
if (DEBUG || DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
- + r + " config to: " + localeAdjustedConfig);
+ + r + " config to: " + config);
int displayId = key.mDisplayId;
boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
DisplayMetrics dm = defaultDisplayMetrics;
@@ -830,7 +764,7 @@
if (tmpConfig == null) {
tmpConfig = new Configuration();
}
- tmpConfig.setTo(localeAdjustedConfig);
+ tmpConfig.setTo(config);
if (!isDefaultDisplay) {
dm = getDisplayMetrics(displayId);
applyNonDefaultDisplayMetricsToConfiguration(dm, tmpConfig);
@@ -840,7 +774,7 @@
}
r.updateConfiguration(tmpConfig, dm, compat);
} else {
- r.updateConfiguration(localeAdjustedConfig, dm, compat);
+ r.updateConfiguration(config, dm, compat);
}
//Slog.i(TAG, "Updated app resources " + v.getKey()
// + " " + r + ": " + r.getConfiguration());
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a672d80..63afdd8 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2191,7 +2191,8 @@
* <em>Note: This API has been limited as of {@link android.os.Build.VERSION_CODES#N} for
* device admins that are not device owner and not profile owner.
* The password can now only be changed if there is currently no password set. Device owner
- * and profile owner can still do this.</em>
+ * and profile owner can still do this when user is unlocked and does not have a managed
+ * profile.</em>
* <p>
* The given password must be sufficient for the current password quality and length constraints
* as returned by {@link #getPasswordQuality(ComponentName)} and
@@ -2217,6 +2218,7 @@
* current constraints or if the user has not been decrypted yet.
* @throws SecurityException if the calling application does not own an active administrator
* that uses {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD}
+ * @throws IllegalStateException if the calling user is locked or has a managed profile.
*/
public boolean resetPassword(String password, int flags) {
throwIfParentInstance("resetPassword");
diff --git a/core/java/android/app/usage/DataUsagePolicy.java b/core/java/android/app/usage/DataUsagePolicy.java
deleted file mode 100644
index ee6b60c..0000000
--- a/core/java/android/app/usage/DataUsagePolicy.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/**
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy
- * of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-
-package android.app.usage;
-
-import android.net.ConnectivityManager;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.IntArray;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Defines a policy for data usage callbacks, made through {@link DataUsagePolicy.Builder} and used
- * to be notified on data usage via {@link NetworkStatsManager#registerDataUsageCallback}.
- * @removed
- */
-public class DataUsagePolicy {
-
- /**
- * Network type to be monitored, as defined in {@link ConnectivityManager}, e.g.
- * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} etc.
- */
- public final int networkType;
-
- /**
- * Set of subscriber ids to be monitored for the given network type. May be empty if not
- * applicable.
- * <p>Should not be modified once created.
- */
- public final String[] subscriberIds;
-
- /**
- * Set of UIDs of which to monitor data usage.
- *
- * <p>If not {@code null}, the caller will be notified when any of the uids exceed
- * the given threshold. If empty all uids for which the calling process has access
- * to stats will be monitored.
- * <p>Should not be modified once created.
- */
- public final int[] uids;
-
- /**
- * Threshold in bytes to be notified on.
- */
- public final long thresholdInBytes;
-
- /**
- * @hide
- */
- DataUsagePolicy(int networkType, String[] subscriberIds, int[] uids,
- long thresholdInBytes) {
- this.networkType = networkType;
- this.subscriberIds = subscriberIds;
- this.uids = uids;
- this.thresholdInBytes = thresholdInBytes;
- }
-
- /**
- * Builder used to create {@link DataUsagePolicy} objects.
- */
- public static class Builder {
- private static final int INVALID_NETWORK_TYPE = -1;
- private int mNetworkType = INVALID_NETWORK_TYPE;
- private List<String> mSubscriberList = new ArrayList<>();
- private IntArray mUids = new IntArray();
- private long mThresholdInBytes;
-
- /**
- * Default constructor for Builder.
- */
- public Builder() {}
-
- /**
- * Build {@link DataUsagePolicy} given the current policies.
- */
- public DataUsagePolicy build() {
- if (mNetworkType == INVALID_NETWORK_TYPE) {
- throw new IllegalArgumentException(
- "DataUsagePolicy requires a valid network type to be set");
- }
- return new DataUsagePolicy(mNetworkType,
- mSubscriberList.toArray(new String[mSubscriberList.size()]),
- mUids.toArray(), mThresholdInBytes);
- }
-
- /**
- * Specifies that the given {@code subscriberId} should be monitored.
- *
- * @param subscriberId the subscriber id of the network interface.
- */
- public Builder addSubscriberId(String subscriberId) {
- mSubscriberList.add(subscriberId);
- return this;
- }
-
- /**
- * Specifies that the given {@code uid} should be monitored.
- */
- public Builder addUid(int uid) {
- mUids.add(uid);
- return this;
- }
-
- /**
- * Specifies that the callback should monitor the given network. It is mandatory
- * to set one.
- *
- * @param networkType As defined in {@link ConnectivityManager}, e.g.
- * {@link ConnectivityManager#TYPE_MOBILE},
- * {@link ConnectivityManager#TYPE_WIFI}, etc.
- */
- public Builder setNetworkType(int networkType) {
- mNetworkType = networkType;
- return this;
- }
-
- /**
- * Sets the threshold in bytes on which the listener should be called. The framework may
- * impose a minimum threshold to avoid too many notifications to be triggered.
- */
- public Builder setThreshold(long thresholdInBytes) {
- mThresholdInBytes = thresholdInBytes;
- return this;
- }
- }
-
- @Override
- public String toString() {
- return "DataUsagePolicy [ networkType=" + networkType
- + ", subscriberIds=" + Arrays.toString(subscriberIds)
- + ", uids=" + Arrays.toString(uids)
- + ", thresholdInBytes=" + thresholdInBytes + " ]";
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof DataUsagePolicy == false) return false;
- DataUsagePolicy that = (DataUsagePolicy) obj;
- return that.networkType == this.networkType
- && Arrays.deepEquals(that.subscriberIds, this.subscriberIds)
- && Arrays.equals(that.uids, this.uids)
- && that.thresholdInBytes == this.thresholdInBytes;
- }
-
- @Override
- public int hashCode() {
- // Start with a non-zero constant.
- int result = 17;
-
- // Include a hash for each field.
- result = 31 * result + networkType;
- result = 31 * result + Arrays.deepHashCode(subscriberIds);
- result = 31 * result + Arrays.hashCode(uids);
- result = 31 * result + (int) (thresholdInBytes ^ (thresholdInBytes >>> 32));
-
- return result;
- }
-}
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 4a28117..720c84a 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -240,18 +240,13 @@
* {@link java.lang.System#currentTimeMillis}.
* @param uid UID of app
* @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
- * @return Statistics object or null if permissions are insufficient or error happened during
- * statistics collection.
+ * @return Statistics object or null if an error happened during statistics collection.
+ * @throws SecurityException if permissions are insufficient to read network statistics.
*/
public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
- long startTime, long endTime, int uid, int tag) {
+ long startTime, long endTime, int uid, int tag) throws SecurityException {
NetworkTemplate template;
- try {
- template = createTemplate(networkType, subscriberId);
- } catch (IllegalArgumentException e) {
- if (DBG) Log.e(TAG, "Cannot create template", e);
- return null;
- }
+ template = createTemplate(networkType, subscriberId);
NetworkStats result;
try {
@@ -303,17 +298,6 @@
return result;
}
- /** @removed */
- public void registerDataUsageCallback(DataUsagePolicy policy, DataUsageCallback callback,
- @Nullable Handler handler) {}
-
- /** @removed */
- public void registerDataUsageCallback(DataUsagePolicy policy, UsageCallback callback,
- @Nullable Handler handler) {}
-
- /** @removed */
- public void unregisterDataUsageCallback(DataUsageCallback callback) {}
-
/**
* Registers to receive notifications about data usage on specified networks.
*
@@ -396,13 +380,6 @@
}
}
- /** @removed */
- public static abstract class DataUsageCallback {
- /** @removed */
- @Deprecated
- public void onLimitReached() {}
- }
-
/**
* Base class for usage callbacks. Should be extended by applications wanting notifications.
*/
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 4c86578..9390bcd 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2045,12 +2045,15 @@
public void onBluetoothServiceDown() {
if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
- mServiceLock.writeLock().lock();
- mService = null;
- if (mLeScanClients != null) mLeScanClients.clear();
- if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup();
- if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup();
- mServiceLock.writeLock().unlock();
+ try {
+ mServiceLock.writeLock().lock();
+ mService = null;
+ if (mLeScanClients != null) mLeScanClients.clear();
+ if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup();
+ if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup();
+ } finally {
+ mServiceLock.writeLock().unlock();
+ }
synchronized (mProxyServiceStateCallbacks) {
for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index a43d06e..108350a 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -285,6 +285,12 @@
public static final int BIND_ADJUST_WITH_ACTIVITY = 0x0080;
/**
+ * @hide Flag for {@link #bindService}: allows application hosting service to manage whitelists
+ * such as temporary allowing a {@code PendingIntent} to bypass Power Save mode.
+ */
+ public static final int BIND_ALLOW_WHITELIST_MANAGEMENT = 0x01000000;
+
+ /**
* @hide Flag for {@link #bindService}: Like {@link #BIND_FOREGROUND_SERVICE},
* but only applies while the device is awake.
*/
@@ -1415,6 +1421,8 @@
* this context. This is typically used to migrate data between storage
* locations after an upgrade, such as migrating to device protected
* storage.
+ * <p>
+ * The database must be closed before being moved.
*
* @param sourceContext The source context which contains the existing
* database to move.
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index c1aac85..f6445e6 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1446,7 +1446,7 @@
*
* @return The locale list.
*/
- public LocaleList getLocales() {
+ public @NonNull LocaleList getLocales() {
fixUpLocaleList();
return mLocaleList;
}
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index dada612..32a2795 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -330,18 +330,43 @@
// doing the conversion here. This impl should be okay because
// we make sure to return a compatible display in the places
// where there are public APIs to retrieve the display... but
- // it would be cleaner and more maintainble to just be
+ // it would be cleaner and more maintainable to just be
// consistently dealing with a compatible display everywhere in
// the framework.
mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
final @Config int configChanges = calcConfigChanges(config);
+ // If even after the update there are no Locales set, grab the default locales.
LocaleList locales = mConfiguration.getLocales();
if (locales.isEmpty()) {
- locales = LocaleList.getAdjustedDefault();
+ locales = LocaleList.getDefault();
mConfiguration.setLocales(locales);
}
+
+ if ((configChanges & ActivityInfo.CONFIG_LOCALE) != 0) {
+ if (locales.size() > 1) {
+ // The LocaleList has changed. We must query the AssetManager's available
+ // Locales and figure out the best matching Locale in the new LocaleList.
+ String[] availableLocales = mAssets.getNonSystemLocales();
+ if (LocaleList.isPseudoLocalesOnly(availableLocales)) {
+ // No app defined locales, so grab the system locales.
+ availableLocales = mAssets.getLocales();
+ if (LocaleList.isPseudoLocalesOnly(availableLocales)) {
+ availableLocales = null;
+ }
+ }
+
+ if (availableLocales != null) {
+ final Locale bestLocale = locales.getFirstMatchWithEnglishSupported(
+ availableLocales);
+ if (bestLocale != null && bestLocale != locales.get(0)) {
+ mConfiguration.setLocales(new LocaleList(bestLocale, locales));
+ }
+ }
+ }
+ }
+
if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
mMetrics.densityDpi = mConfiguration.densityDpi;
mMetrics.density =
@@ -370,7 +395,7 @@
}
mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
- adjustLanguageTag(locales.get(0).toLanguageTag()),
+ adjustLanguageTag(mConfiguration.getLocales().get(0).toLanguageTag()),
mConfiguration.orientation,
mConfiguration.touchscreen,
mConfiguration.densityDpi, mConfiguration.keyboard,
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 49c106e..a9c09c4 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -81,6 +81,4 @@
void setPointerIconType(int typeId);
void setCustomPointerIcon(in PointerIcon icon);
-
- void setPointerIconDetached(boolean detached);
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index a5aeae3..803337b 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -893,24 +893,6 @@
}
}
- /**
- * Update the pointer icon status. When detached, the pointer icon disappears, and further
- * mouse location will be stuck at the current point. Mouse movement events will still arrive,
- * and movement should be handled through {@link MotionEvent.AXIS_RELATIVE_X} and
- * {@link MotionEvent.AXIS_RELATIVE_Y}.
- *
- * @param detached true if the icon will be detached from the actual mouse movement.
- *
- * @hide
- */
- public void setPointerIconDetached(boolean detached) {
- try {
- mIm.setPointerIconDetached(detached);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
-
private void populateInputDevicesLocked() {
if (mInputDevicesChangedListener == null) {
final InputDevicesChangedListener listener = new InputDevicesChangedListener();
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index b6c5c6f..42f5feb 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -334,6 +334,7 @@
*
* @return {@code true} if large transfers should be avoided, otherwise
* {@code false}.
+ * @hide
*/
public boolean isMetered() {
synchronized (this) {
diff --git a/core/java/android/net/PacProxySelector.java b/core/java/android/net/PacProxySelector.java
index 9bdf4f6..85bf79a 100644
--- a/core/java/android/net/PacProxySelector.java
+++ b/core/java/android/net/PacProxySelector.java
@@ -30,6 +30,7 @@
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
+import java.net.URISyntaxException;
import java.util.List;
/**
@@ -67,7 +68,15 @@
String response = null;
String urlString;
try {
+ // Strip path and username/password from URI so it's not visible to PAC script. The
+ // path often contains credentials the app does not want exposed to a potentially
+ // malicious PAC script.
+ if (!"http".equalsIgnoreCase(uri.getScheme())) {
+ uri = new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), "/", null, null);
+ }
urlString = uri.toURL().toString();
+ } catch (URISyntaxException e) {
+ urlString = uri.getHost();
} catch (MalformedURLException e) {
urlString = uri.getHost();
}
diff --git a/core/java/android/net/metrics/DefaultNetworkEvent.java b/core/java/android/net/metrics/DefaultNetworkEvent.java
index 6138b83..f8b5992 100644
--- a/core/java/android/net/metrics/DefaultNetworkEvent.java
+++ b/core/java/android/net/metrics/DefaultNetworkEvent.java
@@ -68,8 +68,28 @@
@Override
public String toString() {
- return String.format("DefaultNetworkEvent(%d -> %d, %s, IPv4: %b, IPv6: %b)", prevNetId,
- netId, NetworkCapabilities.transportNamesOf(transportTypes), prevIPv4, prevIPv6);
+ String prevNetwork = String.valueOf(prevNetId);
+ String newNetwork = String.valueOf(netId);
+ if (prevNetId != 0) {
+ prevNetwork += ":" + ipSupport();
+ }
+ if (netId != 0) {
+ newNetwork += ":" + NetworkCapabilities.transportNamesOf(transportTypes);
+ }
+ return String.format("DefaultNetworkEvent(%s -> %s)", prevNetwork, newNetwork);
+ }
+
+ private String ipSupport() {
+ if (prevIPv4 && prevIPv6) {
+ return "DUAL";
+ }
+ if (prevIPv6) {
+ return "IPv6";
+ }
+ if (prevIPv4) {
+ return "IPv4";
+ }
+ return "NONE";
}
public static final Parcelable.Creator<DefaultNetworkEvent> CREATOR
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 7e1fc15..dc7be6b 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -671,7 +671,7 @@
/**
* N is for ¯\_(ツ)_/¯.
*/
- public static final int N = CUR_DEVELOPMENT;
+ public static final int N = 24;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/LocaleList.java b/core/java/android/os/LocaleList.java
index 8136796..2dc3beb 100644
--- a/core/java/android/os/LocaleList.java
+++ b/core/java/android/os/LocaleList.java
@@ -148,17 +148,6 @@
}
/**
- * It is almost always better to call {@link #getEmptyLocaleList()} instead which returns
- * a pre-constructed empty locale list.
- *
- * @hide
- */
- public LocaleList() {
- mList = sEmptyList;
- mStringRepresentation = "";
- }
-
- /**
* Creates a new {@link LocaleList}.
*
* <p>For empty lists of {@link Locale} items it is better to use {@link #getEmptyLocaleList()},
@@ -409,6 +398,14 @@
}
/**
+ * {@hide}
+ */
+ public int getFirstMatchIndex(String[] supportedLocales) {
+ return computeFirstMatchIndex(Arrays.asList(supportedLocales),
+ false /* assume English is not supported */);
+ }
+
+ /**
* Same as getFirstMatch(), but with English assumed to be supported, even if it's not.
* {@hide}
*/
@@ -437,7 +434,11 @@
* Assumes that there is no repetition in the input.
* {@hide}
*/
- public static boolean isPseudoLocalesOnly(String[] supportedLocales) {
+ public static boolean isPseudoLocalesOnly(@Nullable String[] supportedLocales) {
+ if (supportedLocales == null) {
+ return true;
+ }
+
if (supportedLocales.length > NUM_PSEUDO_LOCALES + 1) {
// This is for optimization. Since there's no repetition in the input, if we have more
// than the number of pseudo-locales plus one for the empty string, it's guaranteed
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index c285acb..ce7a124 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1021,9 +1021,19 @@
}
/**
- * Returns True if the device supports Sustained Performance Mode.
- * Applications Should check if the device supports this mode, before
- * using {@link android.view.Window#setSustainedPerformanceMode}.
+ * This function checks if the device has implemented Sustained Performance
+ * Mode. This needs to be checked only once and is constant for a particular
+ * device/release.
+ *
+ * Sustained Performance Mode is intended to provide a consistent level of
+ * performance for prolonged amount of time.
+ *
+ * Applications should check if the device supports this mode, before using
+ * {@link android.view.Window#setSustainedPerformanceMode}.
+ *
+ * @return Returns True if the device supports it, false otherwise.
+ *
+ * @see android.view.Window#setSustainedPerformanceMode
*/
public boolean isSustainedPerformanceModeSupported() {
return mContext.getResources().getBoolean(
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 403e06c..4abbf0e 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -25,8 +25,10 @@
import android.util.Log;
import java.io.ByteArrayInputStream;
+import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
@@ -45,6 +47,8 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
+import com.android.internal.logging.MetricsLogger;
+
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
@@ -69,6 +73,7 @@
/** Used to communicate with recovery. See bootable/recovery/recovery.cpp. */
private static final File RECOVERY_DIR = new File("/cache/recovery");
private static final File LOG_FILE = new File(RECOVERY_DIR, "log");
+ private static final File LAST_INSTALL_FILE = new File(RECOVERY_DIR, "last_install");
private static final String LAST_PREFIX = "last_";
/**
@@ -682,13 +687,64 @@
}
}
+ // Read last_install; then report time for update and I/O to tron.
+ // Only report on the reboots immediately after an OTA update.
+ private static void parseLastInstallLog(Context context) {
+ try (BufferedReader in = new BufferedReader(new FileReader(LAST_INSTALL_FILE))) {
+ String line = null;
+ int bytesWritten = -1, bytesStashed = -1;
+ int timeTotal = -1;
+ while ((line = in.readLine()) != null) {
+ // Here is an example of lines in last_install:
+ // ...
+ // time_total: 101
+ // bytes_written_vendor: 51074
+ // bytes_stashed_vendor: 200
+ int numIndex = line.indexOf(':');
+ if (numIndex == -1 || numIndex + 1 >= line.length()) {
+ continue;
+ }
+ String numString = line.substring(numIndex + 1).trim();
+ int parsedNum;
+ try {
+ parsedNum = Integer.parseInt(numString);
+ } catch (NumberFormatException ignored) {
+ Log.e(TAG, "Failed to parse numbers in " + line);
+ continue;
+ }
+
+ if (line.startsWith("time")) {
+ timeTotal = parsedNum;
+ } else if (line.startsWith("bytes_written")) {
+ bytesWritten = (bytesWritten == -1) ? parsedNum : bytesWritten + parsedNum;
+ } else if (line.startsWith("bytes_stashed")) {
+ bytesStashed = (bytesStashed == -1) ? parsedNum : bytesStashed + parsedNum;
+ }
+ }
+
+ // Don't report data to tron if corresponding entry isn't found in last_install.
+ if (timeTotal != -1) {
+ MetricsLogger.histogram(context, "ota_time_total", timeTotal);
+ }
+ if (bytesWritten != -1) {
+ MetricsLogger.histogram(context, "ota_bytes_written", bytesWritten);
+ }
+ if (bytesStashed != -1) {
+ MetricsLogger.histogram(context, "ota_bytes_stashed", bytesStashed);
+ }
+
+ } catch (IOException ignored) {
+ Log.e(TAG, "Failed to read lines in last_install", ignored);
+ }
+ }
+
/**
* Called after booting to process and remove recovery-related files.
* @return the log file from recovery, or null if none was found.
*
* @hide
*/
- public static String handleAftermath() {
+ public static String handleAftermath(Context context) {
// Record the tail of the LOG_FILE
String log = null;
try {
@@ -699,6 +755,10 @@
Log.e(TAG, "Error reading recovery log", e);
}
+ if (log != null) {
+ parseLastInstallLog(context);
+ }
+
// Only remove the OTA package if it's partially processed (uncrypt'd).
boolean reservePackage = BLOCK_MAP_FILE.exists();
if (!reservePackage && UNCRYPT_PACKAGE_FILE.exists()) {
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index dcec982..f3dc432 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -924,6 +924,7 @@
/** {@hide} */
public boolean isUserRunning(int userId) {
+ // TODO Switch to using UMS internal isUserRunning
try {
return ActivityManagerNative.getDefault().isUserRunning(userId, 0);
} catch (RemoteException re) {
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index 551ea6b..93afb43 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2016 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.
@@ -11,7 +11,7 @@
* 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.
+ * limitations under the License
*/
package android.os;
@@ -129,15 +129,23 @@
/**
* Return whether the given user is running in an
- * {@link com.android.server.am.UserState#STATE_RUNNING_UNLOCKING "unlocking"} or
- * {@link com.android.server.am.UserState#STATE_RUNNING_UNLOCKED "unlocked"} state.
+ * {@code UserState.STATE_RUNNING_UNLOCKING} or
+ * {@code UserState.STATE_RUNNING_UNLOCKED} state.
*/
public abstract boolean isUserUnlockingOrUnlocked(int userId);
/**
- * Sets whether the given user is running in an
- * {@link com.android.server.am.UserState#STATE_RUNNING_UNLOCKING "unlocking"} or
- * {@link com.android.server.am.UserState#STATE_RUNNING_UNLOCKED "unlocked"} state.
+ * Return whether the given user is running
*/
- public abstract void setUserUnlockingOrUnlocked(int userId, boolean unlockingOrUnlocked);
+ public abstract boolean isUserRunning(int userId);
+
+ /**
+ * Set user's running state
+ */
+ public abstract void setUserState(int userId, int userState);
+
+ /**
+ * Remove user's running state
+ */
+ public abstract void removeUserState(int userId);
}
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index fbf7b26..485bbd1 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -114,6 +114,8 @@
/** {@hide} */
public static final int FLAG_INCLUDE_INVISIBLE = 1 << 10;
+ private static volatile IMountService sMountService = null;
+
private final Context mContext;
private final ContentResolver mResolver;
@@ -1064,15 +1066,17 @@
/** {@hide} */
public static boolean isUserKeyUnlocked(int userId) {
- final IMountService mount = IMountService.Stub
- .asInterface(ServiceManager.getService("mount"));
- if (mount == null) {
+ if (sMountService == null) {
+ sMountService = IMountService.Stub
+ .asInterface(ServiceManager.getService("mount"));
+ }
+ if (sMountService == null) {
Slog.w(TAG, "Early during boot, assuming locked");
return false;
}
final long token = Binder.clearCallingIdentity();
try {
- return mount.isUserKeyUnlocked(userId);
+ return sMountService.isUserKeyUnlocked(userId);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index cbe98f7..f867fb0 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -60,8 +60,8 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
-
import android.util.MemoryIntArray;
+
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.ILockSettings;
@@ -2219,19 +2219,37 @@
* @param outConfig Where to place the configuration settings.
*/
public static void getConfiguration(ContentResolver cr, Configuration outConfig) {
- getConfigurationForUser(cr, outConfig, UserHandle.myUserId());
+ adjustConfigurationForUser(cr, outConfig, UserHandle.myUserId(),
+ false /* updateSettingsIfEmpty */);
}
/** @hide */
- public static void getConfigurationForUser(ContentResolver cr, Configuration outConfig,
- int userHandle) {
+ public static void adjustConfigurationForUser(ContentResolver cr, Configuration outConfig,
+ int userHandle, boolean updateSettingsIfEmpty) {
outConfig.fontScale = Settings.System.getFloatForUser(
cr, FONT_SCALE, DEFAULT_FONT_SCALE, userHandle);
if (outConfig.fontScale < 0) {
outConfig.fontScale = DEFAULT_FONT_SCALE;
}
- outConfig.setLocales(LocaleList.forLanguageTags(
- Settings.System.getStringForUser(cr, SYSTEM_LOCALES, userHandle)));
+
+ final String localeValue =
+ Settings.System.getStringForUser(cr, SYSTEM_LOCALES, userHandle);
+ if (localeValue != null) {
+ outConfig.setLocales(LocaleList.forLanguageTags(localeValue));
+ } else {
+ // Do not update configuration with emtpy settings since we need to take over the
+ // locale list of previous user if the settings value is empty. This happens when a
+ // new user is created.
+
+ if (updateSettingsIfEmpty) {
+ // Make current configuration persistent. This is necessary the first time a
+ // user log in. At the first login, the configuration settings are empty, so we
+ // need to store the adjusted configuration as the initial settings.
+ Settings.System.putStringForUser(
+ cr, SYSTEM_LOCALES, outConfig.getLocales().toLanguageTags(),
+ userHandle);
+ }
+ }
}
/**
@@ -7932,6 +7950,7 @@
* idle_factor (float)
* min_time_to_alarm (long)
* max_temp_app_whitelist_duration (long)
+ * notification_whitelist_duration (long)
* </pre>
*
* <p>
diff --git a/core/java/android/service/carrier/CarrierMessagingService.java b/core/java/android/service/carrier/CarrierMessagingService.java
index 140341c..88a78c3 100644
--- a/core/java/android/service/carrier/CarrierMessagingService.java
+++ b/core/java/android/service/carrier/CarrierMessagingService.java
@@ -56,7 +56,7 @@
* new message notification should be shown.
*
* @see #RECEIVE_OPTIONS_DROP
- * @see #RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE
+ * @see #RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE
*/
public static final int RECEIVE_OPTIONS_DEFAULT = 0;
@@ -72,7 +72,7 @@
* credential-encrypted storage of the device is not available before the user unlocks the
* phone. It is only applicable to devices that support file-based encryption.
*/
- public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 0x2;
+ public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE = 0x2;
/**
* Indicates that an SMS or MMS message was successfully sent.
@@ -148,7 +148,7 @@
* @param subId SMS subscription ID of the SIM
* @param callback result callback. Call with a bitmask integer to indicate how the incoming
* text SMS should be handled by the platform. Use {@link #RECEIVE_OPTIONS_DROP} and
- * {@link #RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE}
+ * {@link #RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE}
* to set the flags in the bitmask.
*/
public void onReceiveTextSms(@NonNull MessagePdu pdu, @NonNull String format,
@@ -157,7 +157,7 @@
@Override
public void onReceiveResult(Boolean result) throws RemoteException {
callback.onReceiveResult(result ? RECEIVE_OPTIONS_DEFAULT : RECEIVE_OPTIONS_DROP
- | RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE);
+ | RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE);
}
});
}
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index 0163b47..447afe6 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -33,7 +33,7 @@
* {@link ConditionProviderService} that owns the rule. Used to tell the system to enter Do Not
* Disturb mode and request that the system exit Do Not Disturb mode.
*/
-public class Condition implements Parcelable {
+public final class Condition implements Parcelable {
@SystemApi
public static final String SCHEME = "condition";
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
index 44c3887..9d4b0a4 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -95,7 +95,7 @@
/**
* A String rule id extra passed to {@link #META_DATA_CONFIGURATION_ACTIVITY}.
*/
- public static final String EXTRA_RULE_ID = "android.content.automatic.ruleId";
+ public static final String EXTRA_RULE_ID = "android.service.notification.extra.RULE_ID";
/**
* Called when this service is connected.
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 37da869..6e6baea 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -18,7 +18,11 @@
import android.annotation.Nullable;
import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Outline;
import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.RemoteViews;
@@ -47,6 +51,18 @@
private int mOriginalNotificationColor;
private boolean mExpanded;
private boolean mShowWorkBadgeAtEnd;
+ private Drawable mBackground;
+ private int mHeaderBackgroundHeight;
+
+ ViewOutlineProvider mProvider = new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ if (mBackground != null) {
+ outline.setRect(0, 0, getWidth(), mHeaderBackgroundHeight);
+ outline.setAlpha(1f);
+ }
+ }
+ };
public NotificationHeaderView(Context context) {
this(context, null);
@@ -66,6 +82,8 @@
com.android.internal.R.dimen.notification_header_shrink_min_width);
mContentEndMargin = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_content_margin_end);
+ mHeaderBackgroundHeight = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_header_background_height);
}
@Override
@@ -165,6 +183,43 @@
return new ViewGroup.MarginLayoutParams(getContext(), attrs);
}
+ /**
+ * Set a {@link Drawable} to be displayed as a background on the header.
+ */
+ public void setHeaderBackgroundDrawable(Drawable drawable) {
+ if (drawable != null) {
+ setWillNotDraw(false);
+ mBackground = drawable;
+ mBackground.setCallback(this);
+ setOutlineProvider(mProvider);
+ } else {
+ setWillNotDraw(true);
+ mBackground = null;
+ setOutlineProvider(null);
+ }
+ invalidate();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (mBackground != null) {
+ mBackground.setBounds(0, 0, getWidth(), mHeaderBackgroundHeight);
+ mBackground.draw(canvas);
+ }
+ }
+
+ @Override
+ protected boolean verifyDrawable(Drawable who) {
+ return super.verifyDrawable(who) || who == mBackground;
+ }
+
+ @Override
+ protected void drawableStateChanged() {
+ if (mBackground != null && mBackground.isStateful()) {
+ mBackground.setState(getDrawableState());
+ }
+ }
+
private void updateTouchListener() {
if (mExpandClickListener != null) {
mTouchListener.bindTouchRects();
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 7b01267..b4131b4 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -46,7 +46,7 @@
boolean allLayers, boolean useIdentityTransform);
private static native void nativeOpenTransaction();
- private static native void nativeCloseTransaction();
+ private static native void nativeCloseTransaction(boolean sync);
private static native void nativeSetAnimationTransaction();
private static native void nativeSetLayer(long nativeObject, int zorder);
@@ -372,7 +372,11 @@
/** end a transaction */
public static void closeTransaction() {
- nativeCloseTransaction();
+ nativeCloseTransaction(false);
+ }
+
+ public static void closeTransactionSync() {
+ nativeCloseTransaction(true);
}
public void deferTransactionUntil(IBinder handle, long frame) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2269282..88605db 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5698,6 +5698,18 @@
/**
* Call this view's OnContextClickListener, if it is defined.
*
+ * @param x the x coordinate of the context click
+ * @param y the y coordinate of the context click
+ * @return True if there was an assigned OnContextClickListener that consumed the event, false
+ * otherwise.
+ */
+ public boolean performContextClick(float x, float y) {
+ return performContextClick();
+ }
+
+ /**
+ * Call this view's OnContextClickListener, if it is defined.
+ *
* @return True if there was an assigned OnContextClickListener that consumed the event, false
* otherwise.
*/
@@ -10044,7 +10056,7 @@
if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
&& (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
|| actionButton == MotionEvent.BUTTON_SECONDARY)) {
- if (performContextClick()) {
+ if (performContextClick(event.getX(), event.getY())) {
mInContextButtonPress = true;
setPressed(true, event.getX(), event.getY());
removeTapCallback();
@@ -15250,7 +15262,6 @@
destroyDrawingCache();
cleanupDraw();
- releasePointerCapture();
mCurrentAnimation = null;
}
@@ -21824,57 +21835,6 @@
return mPointerIcon;
}
-
- /**
- * Request capturing further mouse events.
- *
- * When the view captures, the pointer icon will disappear and will not change its
- * position. Further pointer events will come to the capturing view, and the pointer movements
- * will can be detected through {@link MotionEvent#AXIS_RELATIVE_X} and
- * {@link MotionEvent#AXIS_RELATIVE_Y}. Non-mouse events (touchscreens, or stylus) will not
- * be affected.
- *
- * The capture will be released through {@link #releasePointerCapture()}, or will be lost
- * automatically when the view or containing window disappear.
- *
- * @return true when succeeds.
- * @see #releasePointerCapture()
- * @see #hasPointerCapture()
- */
- public void requestPointerCapture() {
- final ViewRootImpl viewRootImpl = getViewRootImpl();
- if (viewRootImpl != null) {
- viewRootImpl.requestPointerCapture(this);
- }
- }
-
-
- /**
- * Release the current capture of mouse events.
- *
- * If the view does not have the capture, it will do nothing.
- * @see #requestPointerCapture()
- * @see #hasPointerCapture()
- */
- public void releasePointerCapture() {
- final ViewRootImpl viewRootImpl = getViewRootImpl();
- if (viewRootImpl != null) {
- viewRootImpl.releasePointerCapture(this);
- }
- }
-
- /**
- * Checks the capture status of mouse events.
- *
- * @return true if the view has the capture.
- * @see #requestPointerCapture()
- * @see #hasPointerCapture()
- */
- public boolean hasPointerCapture() {
- final ViewRootImpl viewRootImpl = getViewRootImpl();
- return (viewRootImpl != null) && viewRootImpl.hasPointerCapture(this);
- }
-
//
// Properties
//
@@ -22852,6 +22812,11 @@
boolean mKeepScreenOn;
/**
+ * Set during a traveral if the light center needs to be updated.
+ */
+ boolean mNeedsUpdateLightCenter;
+
+ /**
* Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
*/
int mSystemUiVisibility;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 1c6600d..0d648c1 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -80,7 +80,6 @@
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
-import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.widget.Scroller;
@@ -920,6 +919,11 @@
// Recompute system ui visibility.
mAttachInfo.mRecomputeGlobalAttributes = true;
}
+ if ((mWindowAttributesChangesFlag
+ & WindowManager.LayoutParams.LAYOUT_CHANGED) != 0) {
+ // Request to update light center.
+ mAttachInfo.mNeedsUpdateLightCenter = true;
+ }
if (mWindowAttributes.packageName == null) {
mWindowAttributes.packageName = mBasePackageName;
}
@@ -2226,13 +2230,16 @@
}
mAttachInfo.mWindowLeft = frame.left;
mAttachInfo.mWindowTop = frame.top;
-
- // Update the light position for the new window offsets.
+ }
+ if (windowMoved || mAttachInfo.mNeedsUpdateLightCenter) {
+ // Update the light position for the new offsets.
if (mAttachInfo.mHardwareRenderer != null) {
mAttachInfo.mHardwareRenderer.setLightCenter(mAttachInfo);
}
+ mAttachInfo.mNeedsUpdateLightCenter = false;
}
}
+
private void handleOutOfResourcesException(Surface.OutOfResourcesException e) {
Log.e(mTag, "OutOfResourcesException initializing HW surface", e);
try {
@@ -3168,32 +3175,6 @@
}
}
- void requestPointerCapture(View view) {
- if (!mAttachInfo.mHasWindowFocus) {
- Log.w(mTag, "Can't set capture if it's not focused.");
- return;
- }
- if (mCapturingView == view) {
- return;
- }
- mCapturingView = view;
- InputManager.getInstance().setPointerIconDetached(true);
- return;
- }
-
- void releasePointerCapture(View view) {
- if (mCapturingView != view || mCapturingView == null) {
- return;
- }
-
- mCapturingView = null;
- InputManager.getInstance().setPointerIconDetached(false);
- }
-
- boolean hasPointerCapture(View view) {
- return view != null && mCapturingView == view;
- }
-
@Override
public void requestChildFocus(View child, View focused) {
if (DEBUG_INPUT_RESIZE) {
@@ -3271,10 +3252,6 @@
mView = null;
mAttachInfo.mRootView = null;
- if (mCapturingView != null) {
- releasePointerCapture(mCapturingView);
- }
-
mSurface.release();
if (mInputQueueCallback != null && mInputQueue != null) {
@@ -3615,8 +3592,6 @@
.softInputMode &=
~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
mHasHadWindowFocus = true;
- } else if (mCapturingView != null) {
- releasePointerCapture(mCapturingView);
}
}
} break;
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index d0d4507..52f35de 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -16,6 +16,7 @@
package android.view.accessibility;
+import android.annotation.Nullable;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
@@ -101,8 +102,9 @@
/**
* Gets the title of the window.
*
- * @return The title.
+ * @return The title of the window, or {@code null} if none is available.
*/
+ @Nullable
public CharSequence getTitle() {
return mTitle;
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 1618758..4013b30 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1277,6 +1277,28 @@
return true;
}
}
+ } else {
+ if (startInputReason
+ == InputMethodClient.START_INPUT_REASON_WINDOW_FOCUS_GAIN) {
+ // We are here probably because of an obsolete window-focus-in message sent
+ // to windowGainingFocus. Since IMMS determines whether a Window can have
+ // IME focus or not by using the latest window focus state maintained in the
+ // WMS, this kind of race condition cannot be avoided. One obvious example
+ // would be that we have already received a window-focus-out message but the
+ // UI thread is still handling previous window-focus-in message here.
+ // TODO: InputBindResult should have the error code.
+ if (DEBUG) Log.w(TAG, "startInputOrWindowGainedFocus failed. "
+ + "Window focus may have already been lost. "
+ + "win=" + windowGainingFocus + " view=" + dumpViewInfo(view));
+ if (!mActive) {
+ // mHasBeenInactive is a latch switch to forcefully refresh IME focus
+ // state when an inactive (mActive == false) client is gaining window
+ // focus. In case we have unnecessary disable the latch due to this
+ // spurious wakeup, we re-enable the latch here.
+ // TODO: Come up with more robust solution.
+ mHasBeenInactive = true;
+ }
+ }
}
if (mCurMethod != null && mCompletions != null) {
try {
diff --git a/core/java/android/view/inputmethod/InputMethodManagerInternal.java b/core/java/android/view/inputmethod/InputMethodManagerInternal.java
index ce9908c..77df4e3 100644
--- a/core/java/android/view/inputmethod/InputMethodManagerInternal.java
+++ b/core/java/android/view/inputmethod/InputMethodManagerInternal.java
@@ -32,4 +32,9 @@
* Called by the window manager to let the input method manager rotate the input method.
*/
void switchInputMethod(boolean forwardDirection);
+
+ /**
+ * Hides the current input method, if visible.
+ */
+ void hideCurrentInputMethod();
}
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index 66896ab..ac44033 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -16,6 +16,8 @@
package android.widget;
+import com.android.internal.R;
+
import android.annotation.AttrRes;
import android.annotation.ColorInt;
import android.annotation.DrawableRes;
@@ -27,17 +29,16 @@
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
+import android.icu.util.Calendar;
+import android.icu.util.TimeZone;
import android.util.AttributeSet;
import android.util.Log;
-import com.android.internal.R;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
-import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
-import java.util.TimeZone;
/**
* This class is a calendar widget for displaying and selecting dates. The
diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java
index f540479..2b91713 100644
--- a/core/java/android/widget/CalendarViewLegacyDelegate.java
+++ b/core/java/android/widget/CalendarViewLegacyDelegate.java
@@ -27,6 +27,7 @@
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.icu.util.Calendar;
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
@@ -37,7 +38,6 @@
import android.view.View;
import android.view.ViewGroup;
-import java.util.Calendar;
import java.util.Locale;
import libcore.icu.LocaleData;
diff --git a/core/java/android/widget/CalendarViewMaterialDelegate.java b/core/java/android/widget/CalendarViewMaterialDelegate.java
index 0ed75d5..07b2000 100644
--- a/core/java/android/widget/CalendarViewMaterialDelegate.java
+++ b/core/java/android/widget/CalendarViewMaterialDelegate.java
@@ -18,11 +18,10 @@
import android.annotation.StyleRes;
import android.content.Context;
+import android.icu.util.Calendar;
import android.util.AttributeSet;
import android.widget.DayPickerView.OnDaySelectedListener;
-import java.util.Calendar;
-
class CalendarViewMaterialDelegate extends CalendarView.AbstractCalendarViewDelegate {
private final DayPickerView mDayPickerView;
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 0c5edc5..8613f99 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -16,11 +16,15 @@
package android.widget;
+import com.android.internal.R;
+
import android.annotation.Nullable;
import android.annotation.Widget;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
+import android.icu.util.Calendar;
+import android.icu.util.TimeZone;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
@@ -28,11 +32,7 @@
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
-import com.android.internal.R;
-
-import java.util.Calendar;
import java.util.Locale;
-import java.util.TimeZone;
/**
* Provides a widget for selecting a date.
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 0a23b34..2fd52b5 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -26,6 +26,7 @@
import android.content.res.TypedArray;
import android.icu.text.DisplayContext;
import android.icu.text.SimpleDateFormat;
+import android.icu.util.Calendar;
import android.os.Parcelable;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
@@ -40,7 +41,6 @@
import android.widget.DayPickerView.OnDaySelectedListener;
import android.widget.YearPickerView.OnYearSelectedListener;
-import java.util.Calendar;
import java.util.Locale;
/**
@@ -432,7 +432,8 @@
public void setMinDate(long minDate) {
mTempDate.setTimeInMillis(minDate);
if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
- && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
+ && mTempDate.get(Calendar.DAY_OF_YEAR) == mMinDate.get(Calendar.DAY_OF_YEAR)) {
+ // Same day, no-op.
return;
}
if (mCurrentDate.before(mTempDate)) {
@@ -453,7 +454,8 @@
public void setMaxDate(long maxDate) {
mTempDate.setTimeInMillis(maxDate);
if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
- && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
+ && mTempDate.get(Calendar.DAY_OF_YEAR) == mMaxDate.get(Calendar.DAY_OF_YEAR)) {
+ // Same day, no-op.
return;
}
if (mCurrentDate.after(mTempDate)) {
diff --git a/core/java/android/widget/DatePickerSpinnerDelegate.java b/core/java/android/widget/DatePickerSpinnerDelegate.java
index d8a3c56..1a6d351 100644
--- a/core/java/android/widget/DatePickerSpinnerDelegate.java
+++ b/core/java/android/widget/DatePickerSpinnerDelegate.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
+import android.icu.util.Calendar;
import android.os.Parcelable;
import android.text.InputType;
import android.text.TextUtils;
@@ -37,7 +38,6 @@
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
-import java.util.Calendar;
import java.util.Locale;
import libcore.icu.ICU;
@@ -288,7 +288,8 @@
public void setMinDate(long minDate) {
mTempDate.setTimeInMillis(minDate);
if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
- && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
+ && mTempDate.get(Calendar.DAY_OF_YEAR) == mMinDate.get(Calendar.DAY_OF_YEAR)) {
+ // Same day, no-op.
return;
}
mMinDate.setTimeInMillis(minDate);
@@ -311,7 +312,8 @@
public void setMaxDate(long maxDate) {
mTempDate.setTimeInMillis(maxDate);
if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
- && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
+ && mTempDate.get(Calendar.DAY_OF_YEAR) == mMaxDate.get(Calendar.DAY_OF_YEAR)) {
+ // Same day, no-op.
return;
}
mMaxDate.setTimeInMillis(maxDate);
diff --git a/core/java/android/widget/DateTimeView.java b/core/java/android/widget/DateTimeView.java
index d2ee866..e172044 100644
--- a/core/java/android/widget/DateTimeView.java
+++ b/core/java/android/widget/DateTimeView.java
@@ -34,6 +34,7 @@
import android.os.Handler;
import android.text.format.Time;
import android.util.AttributeSet;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.RemoteViews.RemoteView;
import com.android.internal.R;
@@ -118,7 +119,6 @@
public void setTime(long time) {
Time t = new Time();
t.set(time);
- t.second = 0;
mTimeMillis = t.toMillis(false);
mTime = new Date(t.year-1900, t.month, t.monthDay, t.hour, t.minute, 0);
update();
@@ -333,6 +333,63 @@
update();
}
+ @Override
+ public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfoInternal(info);
+ if (mShowRelativeTime) {
+ // The short version of the time might not be completely understandable and for
+ // accessibility we rather have a longer version.
+ long now = System.currentTimeMillis();
+ long duration = Math.abs(now - mTimeMillis);
+ int count;
+ boolean past = (now >= mTimeMillis);
+ String result;
+ if (duration < MINUTE_IN_MILLIS) {
+ result = mNowText;
+ } else if (duration < HOUR_IN_MILLIS) {
+ count = (int)(duration / MINUTE_IN_MILLIS);
+ result = String.format(getContext().getResources().getQuantityString(past
+ ? com.android.internal.
+ R.plurals.duration_minutes_relative
+ : com.android.internal.
+ R.plurals.duration_minutes_relative_future,
+ count),
+ count);
+ } else if (duration < DAY_IN_MILLIS) {
+ count = (int)(duration / HOUR_IN_MILLIS);
+ result = String.format(getContext().getResources().getQuantityString(past
+ ? com.android.internal.
+ R.plurals.duration_hours_relative
+ : com.android.internal.
+ R.plurals.duration_hours_relative_future,
+ count),
+ count);
+ } else if (duration < YEAR_IN_MILLIS) {
+ // In weird cases it can become 0 because of daylight savings
+ TimeZone timeZone = TimeZone.getDefault();
+ count = Math.max(Math.abs(dayDistance(timeZone, mTimeMillis, now)), 1);
+ result = String.format(getContext().getResources().getQuantityString(past
+ ? com.android.internal.
+ R.plurals.duration_days_relative
+ : com.android.internal.
+ R.plurals.duration_days_relative_future,
+ count),
+ count);
+
+ } else {
+ count = (int)(duration / YEAR_IN_MILLIS);
+ result = String.format(getContext().getResources().getQuantityString(past
+ ? com.android.internal.
+ R.plurals.duration_years_relative
+ : com.android.internal.
+ R.plurals.duration_years_relative_future,
+ count),
+ count);
+ }
+ info.setText(result);
+ }
+ }
+
private static class ReceiverInfo {
private final ArrayList<DateTimeView> mAttachedViews = new ArrayList<DateTimeView>();
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index 97936e7..9f02b44 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -25,14 +25,13 @@
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
+import android.icu.util.Calendar;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SimpleMonthView.OnDayClickListener;
-import java.util.Calendar;
-
/**
* An adapter for a list of {@link android.widget.SimpleMonthView} items.
*/
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index dc772fb..ab89c1f 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
+import android.icu.util.Calendar;
import android.util.AttributeSet;
import android.util.MathUtils;
import android.view.LayoutInflater;
@@ -31,7 +32,6 @@
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
-import java.util.Calendar;
import java.util.Locale;
import libcore.icu.LocaleData;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 622567c..15bba3a 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -76,6 +76,7 @@
import android.view.ActionMode;
import android.view.ActionMode.Callback;
import android.view.ContextMenu;
+import android.view.ContextThemeWrapper;
import android.view.DisplayListCanvas;
import android.view.DragAndDropPermissions;
import android.view.DragEvent;
@@ -3004,8 +3005,16 @@
protected abstract int getTextOffset();
protected abstract int getVerticalLocalPosition(int line);
protected abstract int clipVertically(int positionY);
+ protected void setUp() {
+ }
public PinnedPopupWindow() {
+ // Due to calling subclass methods in base constructor, subclass constructor is not
+ // called before subclass methods, e.g. createPopupWindow or initContentView. To give
+ // a chance to initialize subclasses, call setUp() method here.
+ // TODO: It is good to extract non trivial initialization code from constructor.
+ setUp();
+
createPopupWindow();
mPopupWindow.setWindowLayoutType(
@@ -3267,8 +3276,7 @@
private boolean mCursorWasVisibleBeforeSuggestions;
private boolean mIsShowingUp = false;
private SuggestionAdapter mSuggestionsAdapter;
- private final TextAppearanceSpan mHighlightSpan = new TextAppearanceSpan(
- mTextView.getContext(), mTextView.mTextEditSuggestionHighlightStyle);
+ private TextAppearanceSpan mHighlightSpan; // TODO: Make mHighlightSpan final.
private TextView mAddToDictionaryButton;
private TextView mDeleteButton;
private ListView mSuggestionListView;
@@ -3276,8 +3284,10 @@
private int mContainerMarginWidth;
private int mContainerMarginTop;
private LinearLayout mContainerView;
+ private Context mContext; // TODO: Make mContext final.
private class CustomPopupWindow extends PopupWindow {
+
@Override
public void dismiss() {
if (!isShowing()) {
@@ -3301,6 +3311,23 @@
}
@Override
+ protected void setUp() {
+ mContext = applyDefaultTheme(mTextView.getContext());
+ mHighlightSpan = new TextAppearanceSpan(mContext,
+ mTextView.mTextEditSuggestionHighlightStyle);
+ }
+
+ private Context applyDefaultTheme(Context originalContext) {
+ TypedArray a = originalContext.obtainStyledAttributes(
+ new int[]{com.android.internal.R.attr.isLightTheme});
+ boolean isLightTheme = a.getBoolean(0, true);
+ int themeId = isLightTheme ? R.style.ThemeOverlay_Material_Light
+ : R.style.ThemeOverlay_Material_Dark;
+ a.recycle();
+ return new ContextThemeWrapper(originalContext, themeId);
+ }
+
+ @Override
protected void createPopupWindow() {
mPopupWindow = new CustomPopupWindow();
mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
@@ -3311,8 +3338,8 @@
@Override
protected void initContentView() {
- final LayoutInflater inflater = (LayoutInflater) mTextView.getContext().
- getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
mContentView = (ViewGroup) inflater.inflate(
mTextView.mTextEditSuggestionContainerLayout, null);
@@ -3405,8 +3432,8 @@
}
private class SuggestionAdapter extends BaseAdapter {
- private LayoutInflater mInflater = (LayoutInflater) mTextView.getContext().
- getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ private LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
@Override
public int getCount() {
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index 97d834a..588425f 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -32,6 +32,7 @@
import android.graphics.Typeface;
import android.icu.text.DisplayContext;
import android.icu.text.SimpleDateFormat;
+import android.icu.util.Calendar;
import android.os.Bundle;
import android.text.TextPaint;
import android.text.format.DateFormat;
@@ -48,7 +49,6 @@
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import java.text.NumberFormat;
-import java.util.Calendar;
import java.util.Locale;
import libcore.icu.LocaleData;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index fc120eb..5cbd284 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6857,11 +6857,11 @@
.setLineSpacing(mSpacingAdd, mSpacingMult)
.setIncludePad(mIncludePad)
.setBreakStrategy(mBreakStrategy)
- .setHyphenationFrequency(mHyphenationFrequency)
- .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
+ .setHyphenationFrequency(mHyphenationFrequency);
if (shouldEllipsize) {
builder.setEllipsize(mEllipsize)
- .setEllipsizedWidth(ellipsisWidth);
+ .setEllipsizedWidth(ellipsisWidth)
+ .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
}
mHintLayout = builder.build();
}
@@ -6948,12 +6948,11 @@
.setLineSpacing(mSpacingAdd, mSpacingMult)
.setIncludePad(mIncludePad)
.setBreakStrategy(mBreakStrategy)
- .setHyphenationFrequency(mHyphenationFrequency)
- .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
+ .setHyphenationFrequency(mHyphenationFrequency);
if (shouldEllipsize) {
builder.setEllipsize(effectiveEllipsize)
- .setEllipsizedWidth(ellipsisWidth);
-
+ .setEllipsizedWidth(ellipsisWidth)
+ .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
}
// TODO: explore always setting maxLines
result = builder.build();
diff --git a/core/java/android/widget/YearPickerView.java b/core/java/android/widget/YearPickerView.java
index 96624d2..a3f5a67 100644
--- a/core/java/android/widget/YearPickerView.java
+++ b/core/java/android/widget/YearPickerView.java
@@ -16,18 +16,17 @@
package android.widget;
+import com.android.internal.R;
+
import android.content.Context;
import android.content.res.Resources;
+import android.icu.util.Calendar;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
-import java.util.Calendar;
-
-import com.android.internal.R;
-
/**
* Displays a selectable list of years.
*/
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index 5944568..ef2fd0d 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -53,6 +53,8 @@
import android.widget.ImageView;
public class PlatLogoActivity extends Activity {
+ public static final boolean REVEAL_THE_NAME = true;
+
FrameLayout mLayout;
int mTapCount;
int mKeyCount;
@@ -100,6 +102,19 @@
public boolean onLongClick(View v) {
if (mTapCount < 5) return false;
+ if (REVEAL_THE_NAME) {
+ final Drawable overlay = getDrawable(
+ com.android.internal.R.drawable.platlogo_m);
+ overlay.setBounds(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
+ im.getOverlay().clear();
+ im.getOverlay().add(overlay);
+ overlay.setAlpha(0);
+ ObjectAnimator.ofInt(overlay, "alpha", 0, 255)
+ .setDuration(500)
+ .start();
+ return true;
+ }
+
final ContentResolver cr = getContentResolver();
if (Settings.System.getLong(cr, Settings.System.EGG_MODE, 0)
== 0) {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 93dc625..8b02352 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -8153,14 +8153,17 @@
}
private void resetAllStatsLocked() {
+ final long uptimeMillis = mClocks.uptimeMillis();
+ final long elapsedRealtimeMillis = mClocks.elapsedRealtime();
mStartCount = 0;
- initTimes(mClocks.uptimeMillis() * 1000, mClocks.elapsedRealtime() * 1000);
+ initTimes(uptimeMillis * 1000, elapsedRealtimeMillis * 1000);
mScreenOnTimer.reset(false);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
mScreenBrightnessTimer[i].reset(false);
}
mInteractiveTimer.reset(false);
mPowerSaveModeEnabledTimer.reset(false);
+ mLastIdleTimeStart = elapsedRealtimeMillis;
mLongestLightIdleTime = 0;
mLongestFullIdleTime = 0;
mDeviceIdleModeLightTimer.reset(false);
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 5bb8969..4f15ece 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -521,16 +521,22 @@
@Override
public void setTitle(CharSequence title) {
+ setTitle(title, true);
+ }
+
+ public void setTitle(CharSequence title, boolean updateAccessibilityTitle) {
if (mTitleView != null) {
mTitleView.setText(title);
} else if (mDecorContentParent != null) {
mDecorContentParent.setWindowTitle(title);
}
mTitle = title;
- WindowManager.LayoutParams params = getAttributes();
- if (!TextUtils.equals(title, params.accessibilityTitle)) {
- params.accessibilityTitle = TextUtils.stringOrSpannedString(title);
- dispatchWindowAttributesChanged(getAttributes());
+ if (updateAccessibilityTitle) {
+ WindowManager.LayoutParams params = getAttributes();
+ if (!TextUtils.equals(title, params.accessibilityTitle)) {
+ params.accessibilityTitle = TextUtils.stringOrSpannedString(title);
+ dispatchWindowAttributesChanged(getAttributes());
+ }
}
}
diff --git a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
index 07f3801..ddf3a76 100644
--- a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
@@ -231,6 +231,7 @@
popupWindow.setAnchorView(mAnchorView);
popupWindow.setDropDownGravity(mDropDownGravity);
popupWindow.setModal(true);
+ popupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
return popupWindow;
}
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 6b93d8336..05b839d 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -28,6 +28,7 @@
long getLong(in String key, in long defaultValue, in int userId);
String getString(in String key, in String defaultValue, in int userId);
void setLockPattern(in String pattern, in String savedPattern, int userId);
+ void resetKeyStore(int userId);
VerifyCredentialResponse checkPattern(in String pattern, int userId);
VerifyCredentialResponse verifyPattern(in String pattern, long challenge, int userId);
void setLockPassword(in String password, in String savedPassword, int userId);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index a5485da..1beea8c 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -141,6 +141,9 @@
// consider it a complex PIN/password.
public static final int MAX_ALLOWED_SEQUENCE = 3;
+ public static final String PROFILE_KEY_NAME_ENCRYPT = "profile_key_name_encrypt_";
+ public static final String PROFILE_KEY_NAME_DECRYPT = "profile_key_name_decrypt_";
+
private final Context mContext;
private final ContentResolver mContentResolver;
private DevicePolicyManager mDevicePolicyManager;
@@ -532,6 +535,18 @@
}
/**
+ * Use it to reset keystore without wiping work profile
+ */
+ public void resetKeyStore(int userId) {
+ try {
+ getLockSettings().resetKeyStore(userId);
+ } catch (RemoteException e) {
+ // It should not happen
+ Log.e(TAG, "Couldn't reset keystore " + e);
+ }
+ }
+
+ /**
* Clear any lock pattern or password.
*/
public void clearLock(int userHandle) {
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index 6d6c162..fbc51cd 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -127,7 +127,7 @@
.append("\n").toString();
final String bootReason = SystemProperties.get("ro.boot.bootreason", null);
- String recovery = RecoverySystem.handleAftermath();
+ String recovery = RecoverySystem.handleAftermath(ctx);
if (recovery != null && db != null) {
db.addText("SYSTEM_RECOVERY_LOG", headers + recovery);
}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 864a0bf..a9ed9dc 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -223,8 +223,9 @@
SurfaceComposerClient::openGlobalTransaction();
}
-static void nativeCloseTransaction(JNIEnv* env, jclass clazz) {
- SurfaceComposerClient::closeGlobalTransaction();
+
+static void nativeCloseTransaction(JNIEnv* env, jclass clazz, jboolean sync) {
+ SurfaceComposerClient::closeGlobalTransaction(sync);
}
static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) {
@@ -649,7 +650,7 @@
(void*)nativeScreenshot },
{"nativeOpenTransaction", "()V",
(void*)nativeOpenTransaction },
- {"nativeCloseTransaction", "()V",
+ {"nativeCloseTransaction", "(Z)V",
(void*)nativeCloseTransaction },
{"nativeSetAnimationTransaction", "()V",
(void*)nativeSetAnimationTransaction },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c2ff4ef..6c289dc 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -273,6 +273,9 @@
<protected-broadcast android:name="com.android.server.WifiManager.action.DEVICE_IDLE" />
<protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED" />
<protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED" />
+ <protected-broadcast android:name="com.android.server.usb.ACTION_OPEN_IN_APPS" />
+ <protected-broadcast android:name="com.android.server.am.DELETE_DUMPHEAP" />
+ <protected-broadcast android:name="com.android.server.net.action.SNOOZE_WARNING" />
<protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
<protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
<protected-broadcast android:name="android.net.wifi.WIFI_CREDENTIAL_CHANGED" />
@@ -322,6 +325,9 @@
<protected-broadcast android:name="android.net.proxy.PAC_REFRESH" />
<protected-broadcast android:name="android.telecom.action.DEFAULT_DIALER_CHANGED" />
+ <protected-broadcast android:name="android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.CONTENT_CHANGED" />
+ <protected-broadcast android:name="android.provider.Telephony.MMS_DOWNLOADED" />
<protected-broadcast
android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
@@ -384,6 +390,7 @@
<protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_REMOVED" />
<protected-broadcast android:name="android.bluetooth.adapter.action.BLE_STATE_CHANGED" />
+ <protected-broadcast android:name="com.android.bluetooth.map.USER_CONFIRM_TIMEOUT" />
<protected-broadcast android:name="android.content.jobscheduler.JOB_DELAY_EXPIRED" />
<protected-broadcast android:name="android.content.syncmanager.SYNC_ALARM" />
<protected-broadcast android:name="android.media.INTERNAL_RINGER_MODE_CHANGED_ACTION" />
diff --git a/core/res/res/drawable-nodpi/default_wallpaper.png b/core/res/res/drawable-nodpi/default_wallpaper.png
index 91ad252..ce546f0 100644
--- a/core/res/res/drawable-nodpi/default_wallpaper.png
+++ b/core/res/res/drawable-nodpi/default_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/platlogo_m.xml b/core/res/res/drawable-nodpi/platlogo_m.xml
index f19e045..d9a558d 100644
--- a/core/res/res/drawable-nodpi/platlogo_m.xml
+++ b/core/res/res/drawable-nodpi/platlogo_m.xml
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 2015 The Android Open Source Project
+Copyright (C) 2016 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.
@@ -19,19 +19,54 @@
android:viewportWidth="48.0"
android:viewportHeight="48.0">
<path
- android:fillColor="#08000000"
- android:pathData="M13.5,34.5l13.3,13.3c11,-1.3,19.7,-10,21,-21L34.5,13.5L13.5,34.5z"
- />
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M33.8,38l-25.5,-25.5l-1.7000003,0.6999998l25.499998,25.5z"/>
<path
- android:pathData="M24,24c0,0,0,2.4,0,5.2s0,5.2,0,5.2L34.5,24V13.5L24,24z"
- android:fillColor="#FFFFFF"/>
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M40.8,34.8l-25.4,-25.5l-1.6999998,0.6999998l25.5,25.5z"/>
<path
- android:pathData="M24,24L13.5,13.5V24L24,34.5c0,0,0,-2.4,0,-5.2S24,24,24,24z"
- android:fillColor="#EEEEEE"/>
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M11.1,13.1l-0.3,-0.4l1.1,-1.3l0,0l-1.6,0.8l-0.4,-0.4l2.6,-1.2l0.4,0.4l-1.1,1.3l0,0l1.6,-0.8l0.3,0.4L11.1,13.1z"/>
<path
- android:pathData="M13.5,34.5l10.5,0.0l-10.5,-10.5z"
- android:fillColor="#DDDDDD"/>
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M13,14.2l-0.5,-0.5l-0.6,0.2l-0.4,-0.4l3.1,-0.7l0.4,0.4l-2.1,1.7l-0.4,-0.4L13,14.2z M13,13.6l0.3,0.3l0.8,-0.6 l0,0L13,13.6z"/>
<path
- android:pathData="M34.5,34.5l0.0,-10.5l-10.5,10.5z"
- android:fillColor="#DDDDDD"/>
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M16.3,14.6l-1.6,1.2l0,0l2.2,-0.6l0.5,0.5l-2.6,1.2l-0.3,-0.4l0.7,-0.3l1,-0.4l0,0l-2.1,0.5L13.9,16l1.4,-1.1l0,0 l-0.9,0.5l-0.7,0.3l-0.3,-0.4l2.6,-1.2L16.3,14.6z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M17.4,17.8l-0.6,-0.6l-0.7,0.3l0.7,0.7l-0.4,0.2l-1,-1l2.6,-1.2l1,1l-0.4,0.2l-0.7,-0.7L17.2,17l0.6,0.6L17.4,17.8 z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M18.8,18.7L18.8,18.7l1.3,-0.2l0.4,0.4l-2.1,0.3l-0.9,0.4l-0.3,-0.4l1,-0.4l1.2,-1.2l0.4,0.4L18.8,18.7z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M22.2,20.5l-1.6,1.2l0,0l2.2,-0.6l0.5,0.5l-2.6,1.2l-0.3,-0.4l0.7,-0.3l1,-0.4l0,0L20,22.1l-0.2,-0.2l1.4,-1.1l0,0 l-0.9,0.5l-0.7,0.3l-0.3,-0.4l2.6,-1.2L22.2,20.5z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M22,23.6c0,0,0.1,0.1,0.2,0.1c0.1,0,0.2,0,0.3,-0.1l0.3,0.3c-0.2,0.1,-0.4,0.1,-0.6,0.1c-0.2,0,-0.4,-0.1,-0.5,-0.2 c-0.2,-0.2,-0.2,-0.3,-0.1,-0.5c0.1,-0.2,0.2,-0.3,0.5,-0.4l0.2,-0.1c0.3,-0.1,0.5,-0.2,0.8,-0.2c0.2,0,0.5,0.1,0.6,0.3 c0.1,0.1,0.2,0.3,0.1,0.4c0,0.1,-0.2,0.3,-0.4,0.4L23,23.4c0.1,0,0.2,-0.1,0.2,-0.2c0,-0.1,0,-0.1,0,-0.2C23.1,23,23,22.9,22.9,23 c-0.1,0,-0.2,0.1,-0.4,0.1l-0.2,0.1c-0.2,0.1,-0.3,0.1,-0.3,0.2C21.9,23.5,21.9,23.5,22,23.6z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M23.8,25.9l-0.3,-0.4l1.1,-1.3l0,0L22.9,25l-0.4,-0.4l2.6,-1.2l0.4,0.4l-1.1,1.3l0,0l1.6,-0.8l0.3,0.4L23.8,25.9z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M25.7,27l-0.5,-0.5l-0.6,0.2l-0.4,-0.4l3.1,-0.7l0.4,0.4l-2.1,1.7l-0.4,-0.4L25.7,27z M25.7,26.4l0.3,0.3l0.8,-0.6 l0,0L25.7,26.4z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M29,27.4l-1.6,1.2l0,0l2.2,-0.6l0.5,0.5l-2.6,1.2l-0.3,-0.4l0.8,-0.3l1,-0.4l0,0L26.8,29l-0.2,-0.2l1.4,-1.1l0,0 L27,28.1l-0.8,0.3l-0.3,-0.4l2.6,-1.2L29,27.4z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M30,30.6L29.5,30l-0.7,0.3l0.7,0.7L29,31.2l-1,-1l2.6,-1.2l1,1l-0.4,0.2l-0.7,-0.7l-0.6,0.3l0.6,0.6L30,30.6z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M31.5,32.1l-0.6,-0.6L29.8,32l-0.4,-0.4l2.6,-1.2l1,1l-0.4,0.2L32,31l-0.7,0.3l0.6,0.6L31.5,32.1z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M32,33.5L31.6,33L31,33.2l-0.4,-0.4l3.1,-0.7l0.4,0.4l-2.1,1.7l-0.4,-0.4L32,33.5z M32.1,32.9l0.3,0.3l0.8,-0.6 l0,0L32.1,32.9z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M34.3,35.3c-0.3,0.1,-0.5,0.2,-0.8,0.1c-0.2,0,-0.5,-0.1,-0.6,-0.3c-0.2,-0.2,-0.2,-0.4,-0.2,-0.5 c0.1,-0.2,0.2,-0.3,0.6,-0.5l0.8,-0.4c0.3,-0.1,0.6,-0.2,0.9,-0.2c0.3,0,0.5,0.1,0.7,0.3c0.2,0.2,0.3,0.4,0.2,0.5c0,0.2,-0.2,0.3,-0.5,0.5 l-0.3,-0.4c0.2,-0.1,0.3,-0.1,0.3,-0.2c0,-0.1,0,-0.1,-0.1,-0.2C35,34,34.9,34,34.8,34c-0.1,0,-0.3,0,-0.5,0.1l-0.8,0.4 c-0.2,0.1,-0.3,0.2,-0.4,0.2c0,0.1,0,0.1,0,0.2c0.1,0.1,0.2,0.1,0.3,0.1c0.1,0,0.2,0,0.4,-0.1L34.3,35.3z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M36,36.6L35.4,36l-0.7,0.3l0.7,0.7l-0.4,0.2l-1,-1l2.6,-1.2l1,1l-0.4,0.2l-0.7,-0.7l-0.6,0.3l0.6,0.6L36,36.6z"/>
</vector>
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index d16dcc6..38ea92a 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -96,6 +96,7 @@
android:layout_height="wrap_content"
android:paddingTop="1dp"
android:visibility="gone"
+ android:contentDescription="@string/expand_button_content_description"
/>
<ImageView android:id="@+id/profile_badge"
android:layout_width="@dimen/notification_badge_size"
diff --git a/core/res/res/layout/preference_material.xml b/core/res/res/layout/preference_material.xml
index bf0fda9..871b99c 100644
--- a/core/res/res/layout/preference_material.xml
+++ b/core/res/res/layout/preference_material.xml
@@ -67,7 +67,8 @@
android:layout_alignStart="@id/title"
android:textAppearance="?attr/textAppearanceListItemSecondary"
android:textColor="?attr/textColorSecondary"
- android:maxLines="10" />
+ android:maxLines="10"
+ android:ellipsize="end" />
</RelativeLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 44923c9..9fbba38 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Doen \'n fabriekterugstelling om hierdie toestel sonder beperkinge te gebruik"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Raak om meer te wete te kom."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index a648c00..4bab99e 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"ይህን መሣሪያ ያለምንም ገደብ ለመጠቀም የፋብሪካ ዳግም ያስጀምሩ"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"የበለጠ ለመረዳት ይንኩ።"</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 69b5bad..b797006 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1730,4 +1730,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"يمكنك إعادة تعيين بيانات المصنع لاستخدام هذا الجهاز بدون قيود"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"المس للتعرف على مزيد من المعلومات."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 3619b9ad..61f4bf4 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Bu cihazı məhdudiyyətsiz istifadə etmək üçün zavod sıfırlaması edin"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Daha çox məlumat üçün toxunun."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 091d02a..9500deb 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1646,4 +1646,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Resetujte uređaj na fabrička podešavanja da biste ga koristili bez ograničenja"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dodirnite da biste saznali više."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-be-rBY/strings.xml b/core/res/res/values-be-rBY/strings.xml
index 4e419dc..36e6a57 100644
--- a/core/res/res/values-be-rBY/strings.xml
+++ b/core/res/res/values-be-rBY/strings.xml
@@ -1674,4 +1674,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Выканайце скід да заводскіх налад, каб выкарыстоўваць гэту прыладу без абмежаванняў"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Краніце, каб даведацца больш."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 2f41788..06329bc 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Възстановете фабричните настройки на това устройство, за да го използвате без ограничения"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Докоснете, за да научите повече."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index eb6ee1a..2916d95 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"কোনো বিধিনিষেধ ছাড়াই এই ডিভাইসটিকে ব্যবহার করতে ফ্যাক্টরি রিসেট করুন"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"আরো জানতে স্পর্শ করুন৷"</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index 1ea1c66..3c3e488 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -1651,4 +1651,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Vratite uređaj na fabričke postavke kako biste ga koristili bez ograničenja"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dodirnite da saznate više."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 948895c..59bf3e9 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Restableix les dades de fàbrica del dispositiu per utilitzar-lo sense restriccions"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca per obtenir més informació."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 4db961b..7d66b17 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1674,4 +1674,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Chcete-li toto zařízení používat bez omezení, obnovte jej do továrního nastavení"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Klepnutím zobrazíte další informace."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 4121d23..eafad45 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Gendan fabriksdataene på enheden for at bruge den uden begrænsninger"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tryk for at få flere oplysninger."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 595f83d..5510238 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Gerät auf Werkseinstellungen zurücksetzen, um es ohne Einschränkungen zu nutzen"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Für weitere Informationen tippen."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 55c6fa8..bfb52e3 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Επαναφέρετε τις εργοστασιακές ρυθμίσεις για να χρησιμοποιήσετε αυτήν τη συσκευή χωρίς περιορισμούς"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Αγγίξτε για να μάθετε περισσότερα."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index d2e4139..3c399c4 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Factory reset to use this device without restrictions"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touch to find out more."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index d2e4139..3c399c4 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Factory reset to use this device without restrictions"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touch to find out more."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index d2e4139..3c399c4 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Factory reset to use this device without restrictions"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touch to find out more."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index f23c3cc..773dd11 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Restablece la configuración de fábrica para usar este dispositivo sin restricciones"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca para obtener más información."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index fa50f61..93f128c 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Restablece los datos de fábrica para usar este dispositivo sin restricciones"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca para obtener más información."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index c34ad91..329150e 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Seadme piiranguteta kasutamiseks lähtestage see tehaseandmetele"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Lisateabe saamiseks puudutage."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 2b88997..2e813b4 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Berrezarri jatorrizko ezarpenak gailua murriztapenik gabe erabili ahal izateko"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Sakatu informazio gehiago lortzeko."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 2434c34..97264065 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"برای استفاده بدون محدودیت از این دستگاه، بازنشانی کارخانهای انجام دهید"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"برای یادگیری بیشتر لمس کنید."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 24f4098..81fd542 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Palauta tehdasasetukset, jotta voit käyttää tätä laitetta rajoituksitta"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Lue lisätietoja koskettamalla."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 6ecd0fc..bb3ae67 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Rétablissez la configuration d\'usine de cet appareil pour l\'utiliser sans restrictions"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touchez ici pour en savoir plus."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index cdd622f..64d5899 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"− <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Rétablir la configuration d\'usine pour utiliser cet appareil sans restrictions"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Appuyez ici pour en savoir plus."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 5317a84..f57e7bb 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Restablecemento dos valores de fábrica para usar este dispositivo sen restricións"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca para acceder a máis información"</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index c069c15..289582b 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"આ ઉપકરણનો પ્રતિબંધો વિના ઉપયોગ કરવા માટે ફેક્ટરી રીસેટ કરો"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"વધુ જાણવા માટે ટચ કરો."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 6ba19ef..6bf9268 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"इस डिवाइस को प्रतिबंधों के बिना उपयोग करने के लिए फ़ैक्टरी रीसेट करें"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"अधिक जानने के लिए स्पर्श करें."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 60de852..d1e06a6 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1646,4 +1646,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Uređaj je vraćen na tvorničke postavke da biste ga mogli upotrebljavati bez ograničenja"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dodirnite da biste saznali više."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 1a01aca..77c920f 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Állítsa vissza a gyári beállításokat az eszköz korlátozások nélküli használata érdekében"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Érintse meg a további információkért."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 2b935cd..31d9cc1 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -940,7 +940,7 @@
<string name="whichEditApplication" msgid="144727838241402655">"Խմբագրել հետևյալ ծրագրով՝"</string>
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Խմբագրել հետևյալով՝ %1$s"</string>
<string name="whichEditApplicationLabel" msgid="7183524181625290300">"Փոփոխել"</string>
- <string name="whichSendApplication" msgid="6902512414057341668">"Տարածել"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"Կիսվել"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Տարածել ըստ %1$s"</string>
<string name="whichSendApplicationLabel" msgid="4579076294675975354">"Տրամադրել"</string>
<string name="whichSendToApplication" msgid="8272422260066642057">"Ուղարկել այս հավելվածով"</string>
@@ -1219,7 +1219,7 @@
<string name="action_mode_done" msgid="7217581640461922289">"Կատարված է"</string>
<string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"Ջնջում է USB կրիչը..."</string>
<string name="progress_erasing" product="default" msgid="6596988875507043042">"Ջնջում է SD քարտը..."</string>
- <string name="share" msgid="1778686618230011964">"Տարածել"</string>
+ <string name="share" msgid="1778686618230011964">"Կիսվել"</string>
<string name="find" msgid="4808270900322985960">"Գտնել"</string>
<string name="websearch" msgid="4337157977400211589">"Վեբի որոնում"</string>
<string name="find_next" msgid="5742124618942193978">"Գտնել հաջորդը"</string>
@@ -1264,7 +1264,7 @@
<string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Մուտք"</string>
<string name="activitychooserview_choose_application" msgid="2125168057199941199">"Ընտրել ծրագիր"</string>
<string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"Չհաջողվեց գործարկել <xliff:g id="APPLICATION_NAME">%s</xliff:g> ծրագիրը"</string>
- <string name="shareactionprovider_share_with" msgid="806688056141131819">"Տարածել"</string>
+ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Կիսվել"</string>
<string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Կիսվել <xliff:g id="APPLICATION_NAME">%s</xliff:g>-ի հետ"</string>
<string name="content_description_sliding_handle" msgid="415975056159262248">"Սահող բռնակ: Հպել & պահել:"</string>
<string name="description_target_unlock_tablet" msgid="3833195335629795055">"Սահեցրեք` ապակողպելու համար:"</string>
@@ -1312,7 +1312,7 @@
<string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1մատնահետք`"</string>
<string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Տեսնել բոլորը"</string>
<string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Ընտրել գործունեությունը"</string>
- <string name="share_action_provider_share_with" msgid="5247684435979149216">"Տարածել"</string>
+ <string name="share_action_provider_share_with" msgid="5247684435979149216">"Կիսվել"</string>
<string name="sending" msgid="3245653681008218030">"Ուղարկվում է..."</string>
<string name="launchBrowserDefault" msgid="2057951947297614725">"Գործարկե՞լ զննարկիչը:"</string>
<string name="SetupCallDefault" msgid="5834948469253758575">"Ընդունե՞լ զանգը:"</string>
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Սարքն առանց սահմանափակումների օգտագործելու համար կատարեք գործարանային վերակայում"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Հպեք՝ ավելին իմանալու համար:"</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 8e7b87e..1128338 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -546,7 +546,7 @@
<string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Mencegah penggunaan beberapa fitur kunci layar."</string>
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Rumah"</item>
- <item msgid="869923650527136615">"Seluler"</item>
+ <item msgid="869923650527136615">"Ponsel"</item>
<item msgid="7897544654242874543">"Kantor"</item>
<item msgid="1103601433382158155">"Faks Kantor"</item>
<item msgid="1735177144948329370">"Faks Rumah"</item>
@@ -589,7 +589,7 @@
</string-array>
<string name="phoneTypeCustom" msgid="1644738059053355820">"Khusus"</string>
<string name="phoneTypeHome" msgid="2570923463033985887">"Rumah"</string>
- <string name="phoneTypeMobile" msgid="6501463557754751037">"Seluler"</string>
+ <string name="phoneTypeMobile" msgid="6501463557754751037">"Ponsel"</string>
<string name="phoneTypeWork" msgid="8863939667059911633">"Kantor"</string>
<string name="phoneTypeFaxWork" msgid="3517792160008890912">"Faks Kantor"</string>
<string name="phoneTypeFaxHome" msgid="2067265972322971467">"Faks Rumah"</string>
@@ -616,7 +616,7 @@
<string name="emailTypeHome" msgid="449227236140433919">"Rumah"</string>
<string name="emailTypeWork" msgid="3548058059601149973">"Kantor"</string>
<string name="emailTypeOther" msgid="2923008695272639549">"Lainnya"</string>
- <string name="emailTypeMobile" msgid="119919005321166205">"Seluler"</string>
+ <string name="emailTypeMobile" msgid="119919005321166205">"Ponsel"</string>
<string name="postalTypeCustom" msgid="8903206903060479902">"Khusus"</string>
<string name="postalTypeHome" msgid="8165756977184483097">"Rumah"</string>
<string name="postalTypeWork" msgid="5268172772387694495">"Kantor"</string>
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Dikembalikan ke setelan pabrik agar perangkat ini dapat digunakan tanpa batasan"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Sentuh untuk mempelajari lebih lanjut."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 3ca3039e..a65e8d9 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Núllstilltu til að nota þetta tæki án takmarkana"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Snertu til að fá frekari upplýsingar."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index e96927d..7eed840 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Esegui il ripristino dei dati di fabbrica per utilizzare il dispositivo senza limitazioni"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tocca per ulteriori informazioni."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 29e6dec5..dd75ff3 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1674,4 +1674,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"איפוס להגדרות היצרן כדי לאפשר שימוש במכשיר ללא מגבלות"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"גע לקבלת מידע נוסף."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 9618f44..2bd2504 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"制限なしでこの端末を使用するには初期状態にリセットしてください"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"タップして詳細をご確認ください。"</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index c3965e8..3354465 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"ამ მოწყობილობის შეზღუდვების გარეშე გამოსაყენებლად, დააბრუნეთ ქარხნული პარამეტრები"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"შეეხეთ მეტის გასაგებად."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 08cde3e..29a62f3 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Осы құрылғыны шектеусіз пайдалану үшін зауыттық параметрлерді қалпына келтіріңіз"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Қосымша мәліметтер алу үшін түртіңіз."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 2ac5017..31d87de 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1620,4 +1620,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"កំណត់ដូចចេញពីរោងចក្រឡើងវិញដើម្បីប្រើឧបករណ៍នេះដោយគ្មានការរឹតបន្តឹង"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"ប៉ះ ដើម្បីស្វែងយល់បន្ថែម។"</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index be9ded7..c1bac96 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"ನಿರ್ಬಂಧಗಳು ಇಲ್ಲದೆಯೇ ಈ ಸಾಧನವನ್ನು ಬಳಸಲು ಫ್ಯಾಕ್ಟರಿ ಮರುಹೊಂದಿಸಿ"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಸ್ಪರ್ಶಿಸಿ."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index a286605..6cb295c 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"제한 없이 기기를 사용하기 위한 초기화"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"자세한 내용을 보려면 터치하세요."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 371b023..9a1acfa 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Бул түзмөктү чектөөсүз колдонуу үчүн аны баштапкы абалга келтириңиз"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Көбүрөөк билүү үчүн тийип коюңуз."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index cf295a3..ee30deb 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"ຣີເຊັດໃຫ້ເປັນຄ່າໂຮງງານເພື່ອໃຊ້ອຸປະກອນນີ້ໂດຍບໍ່ມີຂໍ້ຈຳກັດ"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"ແຕະເພື່ອສຶກສາເພີ່ມເຕີມ."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 66d6bf8..7204328 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1674,4 +1674,6 @@
<string name="negative_duration" msgid="5688706061127375131">"–<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Atkurkite gamyklinius nustatymus, kad galėtumėte naudoti šį įrenginį be apribojimų"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Palieskite, kad sužinotumėte daugiau."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 71f2a07..9c6c5f7 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1646,4 +1646,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Rūpnīcas datu atiestatīšana ierīces neierobežotai izmantošanai"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Pieskarieties, lai uzzinātu vairāk."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 2b36f1f..638f237 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1623,4 +1623,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Ресетирајте до фабричките поставки за уредов да го користите без ограничувања"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Допрете за да дознаете повеќе."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index ec21238..74b7570 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"നിയന്ത്രണങ്ങൾ ഇല്ലാതെ ഈ ഉപകരണം ഉപയോഗിക്കാൻ ഫാക്ടറി റീസെറ്റ് നടത്തുക"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"കൂടുതലറിയുന്നതിന് സ്പർശിക്കുക."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 0663476..f9ed6c1 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -714,7 +714,7 @@
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Та утсыг тайлах гэж <xliff:g id="NUMBER">%d</xliff:g> удаа буруу оролдлоо. Утас одоо үйлдвэрийн үндсэн утгаараа тохируулагдах болно."</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"<xliff:g id="NUMBER">%d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Хээг мартсан уу?"</string>
- <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Акаунт тайлах"</string>
+ <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Бүртгэл тайлах"</string>
<string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Хээ оруулах оролдлого хэт олон"</string>
<string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"Түгжээг тайлах бол Google акаунтаараа нэвтэрнэ үү."</string>
<string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Хэрэглэгч (имэйл)"</string>
@@ -1068,8 +1068,8 @@
<string name="sms_control_yes" msgid="3663725993855816807">"Зөвшөөрөх"</string>
<string name="sms_control_no" msgid="625438561395534982">"Татгалзах"</string>
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> нь <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b> уруу мессеж илгээх гэж байна."</string>
- <string name="sms_short_code_details" msgid="5873295990846059400">"Энэ таны мобайл акаунтад "<b>"төлбөр нэмэгдүүлж магадгүй"</b>"."</string>
- <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Энэ таны мобайл акаунтад төлбөр нэмэгдүүлж магадгүй."</b></string>
+ <string name="sms_short_code_details" msgid="5873295990846059400">"Энэ таны мобайл бүртгэлд "<b>"төлбөр нэмэгдүүлж магадгүй"</b>"."</string>
+ <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Энэ таны мобайл бүртгэлд төлбөр нэмэгдүүлж магадгүй."</b></string>
<string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Илгээх"</string>
<string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Цуцлах"</string>
<string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Миний сонголтыг санах"</string>
@@ -1173,13 +1173,13 @@
<string name="ime_action_default" msgid="2840921885558045721">"Ажиллуулах"</string>
<string name="dial_number_using" msgid="5789176425167573586">"<xliff:g id="NUMBER">%s</xliff:g> ашиглан \n залгах"</string>
<string name="create_contact_using" msgid="4947405226788104538">"<xliff:g id="NUMBER">%s</xliff:g> дугаар ашиглан \n харилцагч үүсгэх"</string>
- <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"Дараах нэг буюу түүнээс дээш апп таны акаунтад одоо болон дараа хандах зөвшөөрлийг хүсэж байна."</string>
+ <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"Дараах нэг буюу түүнээс дээш апп таны бүртгэлд одоо болон дараа хандах зөвшөөрлийг хүсэж байна."</string>
<string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Та энэ хүсэлтийг зөвшөөрөх үү?"</string>
<string name="grant_permissions_header_text" msgid="6874497408201826708">"Хандах хүсэлт"</string>
<string name="allow" msgid="7225948811296386551">"Зөвшөөрөх"</string>
<string name="deny" msgid="2081879885755434506">"Татгалзах"</string>
<string name="permission_request_notification_title" msgid="6486759795926237907">"Зөвшөөрөл хүсэв"</string>
- <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"<xliff:g id="ACCOUNT">%s</xliff:g> акаунт зөвшөөрөл \n хүссэн"</string>
+ <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"<xliff:g id="ACCOUNT">%s</xliff:g> бүртгэл зөвшөөрөл \n хүссэн"</string>
<string name="forward_intent_to_owner" msgid="1207197447013960896">"Та энэ апп-г өөрийн ажлын профайлаас гадуур ашиглаж байна"</string>
<string name="forward_intent_to_work" msgid="621480743856004612">"Та энэ апп-г өөрийн ажлын профайл дотор ашиглаж байна"</string>
<string name="input_method_binding_label" msgid="1283557179944992649">"Оруулах арга"</string>
@@ -1234,8 +1234,8 @@
<string name="sync_really_delete" msgid="2572600103122596243">"Устгах"</string>
<string name="sync_undo_deletes" msgid="2941317360600338602">"Устгасныг буцаах"</string>
<string name="sync_do_nothing" msgid="3743764740430821845">"Одоо юу ч хийхгүй"</string>
- <string name="choose_account_label" msgid="5655203089746423927">"Акаунт сонгох"</string>
- <string name="add_account_label" msgid="2935267344849993553">"Акаунт нэмэх"</string>
+ <string name="choose_account_label" msgid="5655203089746423927">"Бүртгэл сонгох"</string>
+ <string name="add_account_label" msgid="2935267344849993553">"Бүртгэл нэмэх"</string>
<string name="add_account_button_label" msgid="3611982894853435874">"Аккаунт нэмэх"</string>
<string name="number_picker_increment_button" msgid="2412072272832284313">"Өсөх"</string>
<string name="number_picker_decrement_button" msgid="476050778386779067">"Бууруулах"</string>
@@ -1369,7 +1369,7 @@
<string name="kg_login_submit_button" msgid="5355904582674054702">"Нэвтрэх"</string>
<string name="kg_login_invalid_input" msgid="5754664119319872197">"Хэрэглэгчийн нэр эсвэл нууц үг буруу."</string>
<string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Хэрэглэгчийн нэр нууц үгээ мартсан уу?\n"<b>"google.com/accounts/recovery"</b>"-д зочилно уу."</string>
- <string name="kg_login_checking_password" msgid="1052685197710252395">"Акаунт шалгаж байна…"</string>
+ <string name="kg_login_checking_password" msgid="1052685197710252395">"Бүртгэл шалгаж байна…"</string>
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Та PIN кодоо <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу бичив. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Та PIN кодоо <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу бичив. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурлаа. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
@@ -1379,7 +1379,7 @@
<string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Та таблетыг тайлах гэж <xliff:g id="NUMBER">%d</xliff:g> удаа буруу оролдлоо. Таблет одоо үйлдвэрийн үндсэн утгаараа тохируулагдах болно."</string>
<string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"Та телевизийнхээ түгжээг <xliff:g id="NUMBER">%d</xliff:g> удаа буруу оруулсан байна. Телевиз үйлдвэрээс гарсан анхны тохиргоонд шилжих болно."</string>
<string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Та утсыг тайлах гэж <xliff:g id="NUMBER">%d</xliff:g> удаа буруу оролдлоо. Утас одоо үйлдвэрийн үндсэн утгаараа тохируулагдах болно."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурлаа. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оруулбал, та таблетаа тайлахын тулд имэйл акаунт шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурлаа. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оруулбал, та таблетаа тайлахын тулд имэйл бүртгэл шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Та зурган түгжээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу оруулсан байна. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу оруулсны дараагаар та телевизийнхээ түгжээг и-мэйл дансаа ашиглан тайлах хэрэгтэй болно.\n\n Та <xliff:g id="NUMBER_2">%3$d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурлаа. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оруулбал, та утсаа тайлахын тулд имэйл акаунтаа ашиглах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
@@ -1616,4 +1616,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Энэ төхөөрөмжийг хязгаарлалтгүй ашиглахын тулд үйлдвэрийн тохиргоонд дахин тохируулна уу"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Дэлгэрэнгүй үзэх бол дарна уу."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index d3d5478..bd964f2 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"हे डिव्हाइस निर्बंधांशिवाय वापरण्यासाठी फॅक्टरी रीसेट करा"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"अधिक जाणून घेण्यासाठी स्पर्श करा."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index b49fca9..528b86b 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Lakukan tetapan semula kilang untuk menggunakan peranti ini tanpa sekatan"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Ketik untuk mengetahui lebih lanjut."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index dea7dbe..a508ef2 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"ဤစက်ပစ္စည်းကို ကန့်သတ်ချက်များမပါဘဲ အသုံးပြုရန် စက်ရုံထုတ်ဆက်တင်အတိုင်း ပြန်လည်သတ်မှတ်ပါ"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"ပိုမိုလေ့လာရန် တို့ပါ။"</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 7452f3a..c87f33b 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Tilbakestill til fabrikkstandard for å bruke denne enheten uten begrensninger"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Trykk for å finne ut mer."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index e2b6c64..1c9d96b 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1624,4 +1624,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"यस यन्त्रलाई सीमितताहरू बिना प्रयोग गर्नका लागि फ्याक्ट्री रिसेट गर्नुहोस्"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"थप जान्नका लागि छुनुहोस्।"</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 322b007..fdd6969 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Zet dit apparaat terug op de fabrieksinstellingen om het zonder beperkingen te gebruiken"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tik voor meer informatie."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index 744fdb9..937f045 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਬਿਨਾਂ ਪਾਬੰਦੀਆਂ ਦੇ ਵਰਤਣ ਲਈ ਫੈਕਟਰੀ ਰੀਸੈੱਟ ਕਰੋ"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"ਹੋਰ ਜਾਣਨ ਲਈ ਸਪਰਸ਼ ਕਰੋ।"</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index a44f9430..84734b9 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1674,4 +1674,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Aby używać tego urządzenia bez ograniczeń, przywróć ustawienia fabryczne"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Kliknij, by dowiedzieć się więcej."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index a99a86f..f4edeb6 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Redefinir para a configuração original para usar este dispositivo sem restrições"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toque para saber mais."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index c7088ae..2bea25f 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Repor os dados de fábrica para utilizar o dispositivo sem restrições"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toque para saber mais."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index a99a86f..f4edeb6 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Redefinir para a configuração original para usar este dispositivo sem restrições"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toque para saber mais."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index f28166c..023932e 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1646,4 +1646,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Reveniți la setările din fabrică pentru a folosi acest dispozitiv fără restricții"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Atingeți pentru a afla mai multe."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index fce83ce..4767638 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1674,4 +1674,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Сброс до заводских настроек для работы без ограничений"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Нажмите, чтобы узнать больше."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 17a709c..fc99747 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1620,4 +1620,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"සීමා කිරීම්වලින් තොරව මෙම උපාංගය භාවිත කිරීමට කර්මාන්ත ශාලා යළි සැකසීම"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"තව දැන ගැනීමට ස්පර්ශ කරන්න."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index cac680e..bafb794 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1674,4 +1674,6 @@
<string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Ak chcete toto zariadenie používať bez obmedzení, obnovte na ňom továrenské nastavenia"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Klepnutím získate ďalšie informácie."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 84f5ca8..2780808 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1674,4 +1674,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Ponastavitev naprave na tovarniške nastavitve za uporabo brez omejitev"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dotaknite se, če želite izvedeti več."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index 52ddeb0..fc3fac4 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Rivendos cilësimet e fabrikës për ta përdorur këtë pajisje pa kufizime"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Prek për të mësuar më shumë."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index becd3c8..1a63a3b 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1646,4 +1646,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Ресетујте уређај на фабричка подешавања да бисте га користили без ограничења"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Додирните да бисте сазнали више."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 8add186..f69d620 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Återställ enheten till standardinställningarna om du vill använda den utan begränsningar"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tryck här om du vill läsa mer."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index e8b8631..be3acf0 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1616,4 +1616,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Rejesha mipangilio iliyotoka nayo kiwandani ili utumie kifaa hiki bila vikwazo"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Gusa ili kupata maelezo zaidi."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index d5155a1..8216c50 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"இந்தச் சாதனத்தைக் கட்டுப்பாடுகளின்றிப் பயன்படுத்த, ஆரம்ப நிலைக்கு மீட்டமைக்கவும்"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"மேலும் அறிய தொடவும்."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 56195b7..37ed0e5 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"ఈ పరికరాన్ని ఎటువంటి పరిమితులు లేకుండా ఉపయోగించడానికి ఫ్యాక్టరీ రీసెట్ చేయండి"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"మరింత తెలుసుకోవడానికి తాకండి."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 6415de1..9d20655 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"รีเซ็ตเป็นค่าเริ่มต้นเพื่อใช้อุปกรณ์นี้โดยไร้ข้อจำกัด"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"แตะเพื่อเรียนรู้เพิ่มเติม"</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 83885de..34cc2ce 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"I-factory reset upang magamit ang device na ito nang walang mga paghihigpit"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Pindutin upang matuto nang higit pa."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 9dedf1e..112cdc9 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Bu cihazı kısıtlama olmadan kullanmak için fabrika ayarlarına sıfırlayın"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Daha fazla bilgi edinmek için dokunun."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 1c1547c..4a3c3ff 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1674,4 +1674,6 @@
<string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Відновіть заводські параметри, щоб використовувати пристрій без обмежень"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Торкніться, щоб дізнатися більше."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index bfff0ba..03e961a 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"بغیر کسی حدود کے استعمال کرنے کیلئے اس آلے کو فیکٹری ری سیٹ کریں"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"مزید جاننے کیلئے ٹچ کریں۔"</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 4177d02..3da5c9d 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -1526,7 +1526,7 @@
<string name="package_updated_device_owner" msgid="8856631322440187071">"Administratoringiz tomonidan yangilandi"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Administratoringiz tomonidan o‘chirilgan"</string>
<string name="battery_saver_description" msgid="1960431123816253034">"Batareya quvvatini uzoqroq vaqtga yetkazish uchun quvvat tejash funksiyasi qurilmangiz unumdorligini kamaytiradi hamda uning tebranishi va orqa fonda internetdan foydalanishini cheklaydi. Sinxronlanishni talab qiladigan e-pochta, xabar almashinuv va boshqa ilovalar esa qachonki ularni ishga tushirganingizda yangilanadi.\n\nQurilma quvvat olayotganda quvvat tejash funksiyasi avtomatik tarzda o‘chadi."</string>
- <string name="data_saver_description" msgid="6015391409098303235">"Trafik sarfini kamaytirish maqsadida Trafik tejash funksiyasi ba’zi ilovalarning orqa fonda internetdan foydalanishining oldini oladi. Siz hozirda foydalanayotgan ilova internetdan faqat talab etilgandagina foydalanishi mumkin. Bu degani, masalan, rasmlar ustiga bosilmaguncha, ular yuklanmaydi."</string>
+ <string name="data_saver_description" msgid="6015391409098303235">"Trafik tejash rejimida ayrim ilovalar uchun orqa fondan internetdan foydalanish imkoniyati cheklanadi. Siz ishlatayotgan ilova zaruratga qarab internet-trafik sarflashi mumkin, biroq cheklangan miqdorda. Masalan, rasmlar ustiga bosmaguningizcha ular yuklanmaydi."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"Trafik tejash yoqilsinmi?"</string>
<string name="data_saver_enable_button" msgid="7147735965247211818">"Yoqish"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
@@ -1621,4 +1621,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Bu qurilmadan cheklovlarsiz foydalanish uchun zavod sozlamalarini tiklang"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Ko‘proq o‘rganish uchun bosing."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 73d4926..cb315d9 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Khôi phục cài đặt gốc để sử dụng thiết bị này mà không bị hạn chế"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Chạm để tìm hiểu thêm."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index defd0a6..505d5a0 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"恢复出厂设置即可正常使用此设备,不受任何限制"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"触摸即可了解详情。"</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 4b1cfbb..33ab32e 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"將此裝置回復至原廠設定後,使用將不受限制"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"輕觸以瞭解詳情。"</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 9118331..c6211cd 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"恢復原廠設定即可正常使用這個裝置"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"輕觸即可瞭解詳情。"</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 55d4b73..f0e7f2b 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1618,4 +1618,6 @@
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Setha kabusha ukuze usebenzise idivayisi ngaphandle kwemikhawulo"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Thinta ukuze ufunde kabanzi."</string>
+ <!-- no translation found for suspended_widget_accessibility (6712143096475264190) -->
+ <skip />
</resources>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 30e23f5..e190bd1 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -22,296 +22,120 @@
<!-- Do not translate. These are all of the drawable resources that should be preloaded by
the zygote process before it starts forking application processes. -->
<array name="preloaded_drawables">
- <item>@drawable/toast_frame</item>
- <item>@drawable/btn_check_on_pressed_holo_light</item>
- <item>@drawable/btn_check_on_pressed_holo_dark</item>
- <item>@drawable/btn_check_on_holo_light</item>
- <item>@drawable/btn_check_on_holo_dark</item>
- <item>@drawable/btn_check_on_focused_holo_light</item>
- <item>@drawable/btn_check_on_focused_holo_dark</item>
- <item>@drawable/btn_check_on_disabled_holo_light</item>
- <item>@drawable/btn_check_on_disabled_holo_dark</item>
- <item>@drawable/btn_check_on_disabled_focused_holo_light</item>
- <item>@drawable/btn_check_on_disabled_focused_holo_dark</item>
- <item>@drawable/btn_check_off_pressed_holo_light</item>
- <item>@drawable/btn_check_off_pressed_holo_dark</item>
- <item>@drawable/btn_check_off_holo_light</item>
- <item>@drawable/btn_check_off_holo_dark</item>
- <item>@drawable/btn_check_off_focused_holo_light</item>
- <item>@drawable/btn_check_off_focused_holo_dark</item>
- <item>@drawable/btn_check_off_disabled_holo_light</item>
- <item>@drawable/btn_check_off_disabled_holo_dark</item>
- <item>@drawable/btn_check_off_disabled_focused_holo_light</item>
- <item>@drawable/btn_check_off_disabled_focused_holo_dark</item>
- <item>@drawable/btn_check_holo_light</item>
- <item>@drawable/btn_check_holo_dark</item>
- <item>@drawable/btn_radio_on_pressed_holo_light</item>
- <item>@drawable/btn_radio_on_pressed_holo_dark</item>
- <item>@drawable/btn_radio_on_holo_light</item>
- <item>@drawable/btn_radio_on_holo_dark</item>
- <item>@drawable/btn_radio_on_focused_holo_light</item>
- <item>@drawable/btn_radio_on_focused_holo_dark</item>
- <item>@drawable/btn_radio_on_disabled_holo_light</item>
- <item>@drawable/btn_radio_on_disabled_holo_dark</item>
- <item>@drawable/btn_radio_on_disabled_focused_holo_light</item>
- <item>@drawable/btn_radio_on_disabled_focused_holo_dark</item>
- <item>@drawable/btn_radio_off_pressed_holo_light</item>
- <item>@drawable/btn_radio_off_pressed_holo_dark</item>
- <item>@drawable/btn_radio_off_holo_light</item>
- <item>@drawable/btn_radio_off_holo_dark</item>
- <item>@drawable/btn_radio_off_focused_holo_light</item>
- <item>@drawable/btn_radio_off_focused_holo_dark</item>
- <item>@drawable/btn_radio_off_disabled_holo_light</item>
- <item>@drawable/btn_radio_off_disabled_holo_dark</item>
- <item>@drawable/btn_radio_off_disabled_focused_holo_light</item>
- <item>@drawable/btn_radio_off_disabled_focused_holo_dark</item>
- <item>@drawable/btn_default_pressed_holo_light</item>
- <item>@drawable/btn_default_pressed_holo_dark</item>
- <item>@drawable/btn_default_normal_holo_light</item>
- <item>@drawable/btn_default_normal_holo_dark</item>
- <item>@drawable/btn_default_focused_holo_light</item>
- <item>@drawable/btn_default_focused_holo_dark</item>
- <item>@drawable/btn_default_disabled_holo_light</item>
- <item>@drawable/btn_default_disabled_holo_dark</item>
- <item>@drawable/btn_default_disabled_focused_holo_light</item>
- <item>@drawable/btn_default_disabled_focused_holo_dark</item>
- <item>@drawable/btn_default_holo_dark</item>
- <item>@drawable/btn_default_holo_light</item>
- <item>@drawable/edit_text_holo_light</item>
- <item>@drawable/edit_text_holo_dark</item>
- <item>@drawable/text_cursor_holo_light</item>
- <item>@drawable/text_cursor_holo_dark</item>
- <item>@drawable/text_edit_paste_window</item>
- <item>@drawable/expander_close_holo_dark</item>
- <item>@drawable/expander_close_holo_light</item>
- <item>@drawable/expander_group_holo_dark</item>
- <item>@drawable/expander_group_holo_light</item>
- <item>@drawable/list_selector_holo_dark</item>
- <item>@drawable/list_selector_holo_light</item>
- <item>@drawable/list_section_divider_holo_light</item>
- <item>@drawable/list_section_divider_holo_dark</item>
- <item>@drawable/menu_dropdown_panel_holo_light</item>
- <item>@drawable/menu_dropdown_panel_holo_dark</item>
- <item>@drawable/menu_panel_holo_light</item>
- <item>@drawable/menu_panel_holo_dark</item>
- <item>@drawable/spinner_16_outer_holo</item>
- <item>@drawable/spinner_16_inner_holo</item>
- <item>@drawable/spinner_48_outer_holo</item>
- <item>@drawable/spinner_48_inner_holo</item>
- <item>@drawable/progress_bg_holo_dark</item>
- <item>@drawable/progress_bg_holo_light</item>
- <item>@drawable/progress_horizontal_holo_dark</item>
- <item>@drawable/progress_horizontal_holo_light</item>
- <item>@drawable/progress_large_holo</item>
- <item>@drawable/progress_medium_holo</item>
- <item>@drawable/progress_primary_holo_dark</item>
- <item>@drawable/progress_primary_holo_light</item>
- <item>@drawable/progress_secondary_holo_dark</item>
- <item>@drawable/progress_secondary_holo_light</item>
- <item>@drawable/progress_small_holo</item>
- <item>@drawable/scrubber_progress_horizontal_holo_dark</item>
- <item>@drawable/scrubber_progress_horizontal_holo_light</item>
- <item>@drawable/background_holo_light</item>
- <item>@drawable/background_holo_dark</item>
- <item>@drawable/screen_background_dark</item>
- <item>@drawable/screen_background_dark_transparent</item>
- <item>@drawable/screen_background_light</item>
- <item>@drawable/screen_background_light_transparent</item>
- <item>@drawable/screen_background_selector_dark</item>
- <item>@drawable/screen_background_selector_light</item>
- <item>@drawable/scrollbar_handle_holo_dark</item>
- <item>@drawable/scrollbar_handle_holo_light</item>
- <item>@drawable/spinner_background_holo_dark</item>
- <item>@drawable/spinner_background_holo_light</item>
- <item>@drawable/spinner_ab_default_holo_dark</item>
- <item>@drawable/spinner_ab_default_holo_light</item>
- <item>@drawable/spinner_ab_disabled_holo_dark</item>
- <item>@drawable/spinner_ab_disabled_holo_light</item>
- <item>@drawable/spinner_ab_focused_holo_dark</item>
- <item>@drawable/spinner_ab_focused_holo_light</item>
- <item>@drawable/spinner_ab_pressed_holo_dark</item>
- <item>@drawable/spinner_ab_pressed_holo_light</item>
- <item>@drawable/spinner_ab_holo_dark</item>
- <item>@drawable/spinner_ab_holo_light</item>
- <item>@drawable/spinner_default_holo_dark</item>
- <item>@drawable/spinner_default_holo_light</item>
- <item>@drawable/spinner_disabled_holo_dark</item>
- <item>@drawable/spinner_disabled_holo_light</item>
- <item>@drawable/spinner_focused_holo_dark</item>
- <item>@drawable/spinner_focused_holo_light</item>
- <item>@drawable/spinner_pressed_holo_dark</item>
- <item>@drawable/spinner_pressed_holo_light</item>
- <item>@drawable/cab_background_bottom_holo_dark</item>
- <item>@drawable/cab_background_top_holo_light</item>
- <item>@drawable/cab_background_bottom_holo_light</item>
- <item>@drawable/ic_cab_done_holo_dark</item>
- <item>@drawable/cab_background_top_holo_dark</item>
- <item>@drawable/ic_cab_done_holo_light</item>
- <item>@drawable/btn_cab_done_default_holo_dark</item>
- <item>@drawable/btn_cab_done_focused_holo_light</item>
- <item>@drawable/btn_cab_done_default_holo_light</item>
- <item>@drawable/btn_cab_done_pressed_holo_dark</item>
- <item>@drawable/btn_cab_done_focused_holo_dark</item>
- <item>@drawable/btn_cab_done_pressed_holo_light</item>
- <item>@drawable/btn_cab_done_holo_light</item>
- <item>@drawable/btn_cab_done_holo_dark</item>
- <item>@drawable/ic_menu_close_clear_cancel</item>
- <item>@drawable/ic_menu_copy_holo_dark</item>
- <item>@drawable/ic_menu_copy_holo_light</item>
- <item>@drawable/ic_menu_cut_holo_dark</item>
- <item>@drawable/ic_menu_cut_holo_light</item>
- <item>@drawable/ic_menu_more</item>
- <item>@drawable/ic_menu_moreoverflow_holo_dark</item>
- <item>@drawable/ic_menu_moreoverflow_holo_light</item>
- <item>@drawable/ic_menu_paste_holo_dark</item>
- <item>@drawable/ic_menu_paste_holo_light</item>
- <item>@drawable/ic_menu_selectall_holo_light</item>
- <item>@drawable/ic_menu_selectall_holo_dark</item>
- <item>@drawable/ic_clear</item>
- <item>@drawable/ic_clear_disabled</item>
- <item>@drawable/ic_clear_normal</item>
- <item>@drawable/ic_search_api_holo_dark</item>
- <item>@drawable/ic_search_api_holo_light</item>
- <item>@drawable/ic_go</item>
- <item>@drawable/ic_voice_search_api_holo_dark</item>
- <item>@drawable/ic_voice_search_api_holo_light</item>
- <item>@drawable/dialog_bottom_holo_dark</item>
- <item>@drawable/dialog_bottom_holo_light</item>
- <item>@drawable/dialog_middle_holo_dark</item>
- <item>@drawable/dialog_middle_holo_light</item>
- <item>@drawable/dialog_top_holo_dark</item>
- <item>@drawable/dialog_top_holo_light</item>
- <item>@drawable/ic_dialog_alert_holo_dark</item>
- <item>@drawable/ic_dialog_alert_holo_light</item>
- <item>@drawable/list_divider_holo_dark</item>
- <item>@drawable/list_divider_holo_light</item>
- <item>@drawable/list_divider_holo_light</item>
- <item>@drawable/ab_transparent_dark_holo</item>
- <item>@drawable/ab_stacked_transparent_dark_holo</item>
- <item>@drawable/ab_bottom_transparent_dark_holo</item>
- <item>@drawable/ab_solid_dark_holo</item>
- <item>@drawable/ab_stacked_solid_dark_holo</item>
- <item>@drawable/ab_bottom_solid_dark_holo</item>
- <item>@drawable/ab_transparent_light_holo</item>
- <item>@drawable/ab_stacked_transparent_light_holo</item>
- <item>@drawable/ab_bottom_transparent_light_holo</item>
- <item>@drawable/ab_solid_light_holo</item>
- <item>@drawable/ab_stacked_solid_light_holo</item>
- <item>@drawable/ab_bottom_solid_light_holo</item>
- <item>@drawable/ab_solid_shadow_holo</item>
- <item>@drawable/item_background_holo_dark</item>
- <item>@drawable/item_background_holo_light</item>
- <item>@drawable/fastscroll_thumb_holo</item>
- <item>@drawable/fastscroll_thumb_pressed_holo</item>
- <item>@drawable/fastscroll_thumb_default_holo</item>
- <item>@drawable/fastscroll_track_holo_dark</item>
- <item>@drawable/fastscroll_track_pressed_holo_dark</item>
- <item>@drawable/fastscroll_track_default_holo_dark</item>
- <item>@drawable/fastscroll_track_holo_light</item>
- <item>@drawable/fastscroll_track_pressed_holo_light</item>
- <item>@drawable/fastscroll_track_default_holo_light</item>
- <item>@drawable/editbox_dropdown_background_dark</item>
- <item>@drawable/textfield_searchview_holo_dark</item>
- <item>@drawable/textfield_searchview_right_holo_dark</item>
- <item>@drawable/textfield_searchview_holo_light</item>
- <item>@drawable/textfield_searchview_right_holo_light</item>
- <item>@drawable/textfield_search_selected_holo_dark</item>
- <item>@drawable/textfield_search_default_holo_dark</item>
- <item>@drawable/textfield_search_right_selected_holo_dark</item>
- <item>@drawable/textfield_search_right_default_holo_dark</item>
- <item>@drawable/textfield_search_selected_holo_light</item>
- <item>@drawable/textfield_search_default_holo_light</item>
- <item>@drawable/textfield_search_right_selected_holo_light</item>
- <item>@drawable/textfield_search_right_default_holo_light</item>
- <item>@drawable/tab_indicator_holo</item>
- <item>@drawable/tab_unselected_holo</item>
- <item>@drawable/tab_selected_holo</item>
- <item>@drawable/tab_unselected_focused_holo</item>
- <item>@drawable/tab_selected_focused_holo</item>
- <item>@drawable/tab_unselected_pressed_holo</item>
- <item>@drawable/tab_selected_pressed_holo</item>
- <item>@drawable/quickcontact_badge_overlay_dark</item>
- <item>@drawable/quickcontact_badge_overlay_normal_dark</item>
- <item>@drawable/quickcontact_badge_overlay_pressed_dark</item>
- <item>@drawable/quickcontact_badge_overlay_light</item>
- <item>@drawable/quickcontact_badge_overlay_normal_light</item>
- <item>@drawable/quickcontact_badge_overlay_pressed_light</item>
-
- <!-- Material assets -->
- <item>@drawable/ab_share_pack_material</item>
- <item>@drawable/ab_solid_shadow_material</item>
- <item>@drawable/activated_background_material</item>
- <item>@drawable/btn_borderless_material</item>
- <item>@drawable/btn_check_material_anim</item>
- <item>@drawable/btn_default_material</item>
- <item>@drawable/btn_radio_material_anim</item>
- <item>@drawable/btn_star_material</item>
- <item>@drawable/btn_toggle_material</item>
- <item>@drawable/cab_background_bottom_material</item>
- <item>@drawable/cab_background_top_material</item>
- <item>@drawable/dialog_background_material</item>
- <item>@drawable/edit_text_material</item>
- <item>@drawable/expander_group_material</item>
- <item>@drawable/fastscroll_label_left_material</item>
- <item>@drawable/fastscroll_label_right_material</item>
- <item>@drawable/fastscroll_thumb_material</item>
- <item>@drawable/fastscroll_track_material</item>
- <item>@drawable/floating_popup_background_dark</item>
- <item>@drawable/floating_popup_background_light</item>
- <item>@drawable/ic_ab_back_material</item>
- <item>@drawable/ic_ab_back_material_dark</item>
- <item>@drawable/ic_ab_back_material_light</item>
- <item>@drawable/ic_clear_material</item>
- <item>@drawable/ic_commit_search_api_material</item>
- <item>@drawable/ic_dialog_alert_material</item>
- <item>@drawable/ic_find_next_material</item>
- <item>@drawable/ic_find_previous_material</item>
- <item>@drawable/ic_go_search_api_material</item>
- <item>@drawable/ic_media_route_connecting_material</item>
- <item>@drawable/ic_media_route_material</item>
- <item>@drawable/ic_menu_copy_material</item>
- <item>@drawable/ic_menu_cut_material</item>
- <item>@drawable/ic_menu_find_material</item>
- <item>@drawable/ic_menu_moreoverflow_material</item>
- <item>@drawable/ic_menu_paste_material</item>
- <item>@drawable/ic_menu_search_material</item>
- <item>@drawable/ic_menu_selectall_material</item>
- <item>@drawable/ic_menu_share_material</item>
- <item>@drawable/ic_search_api_material</item>
- <item>@drawable/ic_voice_search_api_material</item>
- <item>@drawable/item_background_borderless_material</item>
- <item>@drawable/item_background_borderless_material_dark</item>
- <item>@drawable/item_background_borderless_material_light</item>
- <item>@drawable/item_background_material</item>
- <item>@drawable/item_background_material_dark</item>
- <item>@drawable/item_background_material_light</item>
- <item>@drawable/list_divider_material</item>
- <item>@drawable/list_section_divider_material</item>
- <item>@drawable/notification_material_action_background</item>
- <item>@drawable/notification_material_media_action_background</item>
- <item>@drawable/popup_background_material</item>
- <item>@drawable/progress_horizontal_material</item>
- <item>@drawable/progress_indeterminate_horizontal_material</item>
- <item>@drawable/progress_large_material</item>
- <item>@drawable/progress_medium_material</item>
- <item>@drawable/progress_small_material</item>
- <item>@drawable/ratingbar_material</item>
- <item>@drawable/ratingbar_small_material</item>
- <item>@drawable/ratingbar_indicator_material</item>
- <item>@drawable/scrollbar_handle_material</item>
- <item>@drawable/seekbar_thumb_material_anim</item>
- <item>@drawable/seekbar_track_material</item>
- <item>@drawable/spinner_background_material</item>
- <item>@drawable/spinner_textfield_background_material</item>
- <item>@drawable/switch_thumb_material_anim</item>
- <item>@drawable/switch_track_material</item>
- <item>@drawable/tab_indicator_material</item>
- <item>@drawable/text_cursor_material</item>
- <item>@drawable/textfield_search_material</item>
- <item>@drawable/text_select_handle_left_material</item>
- <item>@drawable/text_select_handle_middle_material</item>
- <item>@drawable/text_select_handle_right_material</item>
- <item>@drawable/ic_account_circle</item>
+ <item>@drawable/ab_share_pack_material</item>
+ <item>@drawable/ab_solid_shadow_material</item>
+ <item>@drawable/action_bar_item_background_material</item>
+ <item>@drawable/activated_background_material</item>
+ <item>@drawable/btn_borderless_material</item>
+ <item>@drawable/btn_check_material_anim</item>
+ <item>@drawable/btn_colored_material</item>
+ <item>@drawable/btn_default_material</item>
+ <item>@drawable/btn_group_holo_dark</item>
+ <item>@drawable/btn_group_holo_light</item>
+ <item>@drawable/btn_radio_material_anim</item>
+ <item>@drawable/btn_star_material</item>
+ <item>@drawable/btn_toggle_material</item>
+ <item>@drawable/button_inset</item>
+ <item>@drawable/cab_background_bottom_material</item>
+ <item>@drawable/cab_background_top_material</item>
+ <item>@drawable/control_background_32dp_material</item>
+ <item>@drawable/control_background_40dp_material</item>
+ <item>@drawable/dialog_background_material</item>
+ <item>@drawable/editbox_dropdown_background_dark</item>
+ <item>@drawable/edit_text_material</item>
+ <item>@drawable/expander_group_material</item>
+ <item>@drawable/fastscroll_label_left_material</item>
+ <item>@drawable/fastscroll_label_right_material</item>
+ <item>@drawable/fastscroll_thumb_material</item>
+ <item>@drawable/fastscroll_track_material</item>
+ <item>@drawable/floating_popup_background_dark</item>
+ <item>@drawable/floating_popup_background_light</item>
+ <item>@drawable/gallery_item_background</item>
+ <item>@drawable/ic_ab_back_material</item>
+ <item>@drawable/ic_ab_back_material_dark</item>
+ <item>@drawable/ic_ab_back_material_light</item>
+ <item>@drawable/ic_account_circle</item>
+ <item>@drawable/ic_arrow_drop_right_black_24dp</item>
+ <item>@drawable/ic_clear</item>
+ <item>@drawable/ic_clear_disabled</item>
+ <item>@drawable/ic_clear_material</item>
+ <item>@drawable/ic_clear_normal</item>
+ <item>@drawable/ic_commit_search_api_material</item>
+ <item>@drawable/ic_dialog_alert_material</item>
+ <item>@drawable/ic_find_next_material</item>
+ <item>@drawable/ic_find_previous_material</item>
+ <item>@drawable/ic_go</item>
+ <item>@drawable/ic_go_search_api_material</item>
+ <item>@drawable/ic_media_route_connecting_material</item>
+ <item>@drawable/ic_media_route_material</item>
+ <item>@drawable/ic_menu_close_clear_cancel</item>
+ <item>@drawable/ic_menu_copy_material</item>
+ <item>@drawable/ic_menu_cut_material</item>
+ <item>@drawable/ic_menu_find_material</item>
+ <item>@drawable/ic_menu_more</item>
+ <item>@drawable/ic_menu_moreoverflow_material</item>
+ <item>@drawable/ic_menu_paste_material</item>
+ <item>@drawable/ic_menu_search_material</item>
+ <item>@drawable/ic_menu_selectall_material</item>
+ <item>@drawable/ic_menu_share_material</item>
+ <item>@drawable/ic_search_api_material</item>
+ <item>@drawable/ic_voice_search_api_material</item>
+ <item>@drawable/indicator_check_mark_dark</item>
+ <item>@drawable/indicator_check_mark_light</item>
+ <item>@drawable/item_background_borderless_material</item>
+ <item>@drawable/item_background_borderless_material_dark</item>
+ <item>@drawable/item_background_borderless_material_light</item>
+ <item>@drawable/item_background_material</item>
+ <item>@drawable/item_background_material_dark</item>
+ <item>@drawable/item_background_material_light</item>
+ <item>@drawable/list_choice_background_material</item>
+ <item>@drawable/list_divider_material</item>
+ <item>@drawable/list_section_divider_material</item>
+ <item>@drawable/menu_background_fill_parent_width</item>
+ <item>@drawable/notification_material_action_background</item>
+ <item>@drawable/notification_material_media_action_background</item>
+ <item>@drawable/number_picker_divider_material</item>
+ <item>@drawable/popup_background_material</item>
+ <item>@drawable/popup_inline_error_above_holo_dark</item>
+ <item>@drawable/popup_inline_error_above_holo_light</item>
+ <item>@drawable/popup_inline_error_holo_dark</item>
+ <item>@drawable/popup_inline_error_holo_light</item>
+ <item>@drawable/progress_horizontal_material</item>
+ <item>@drawable/progress_indeterminate_horizontal_material</item>
+ <item>@drawable/progress_large_material</item>
+ <item>@drawable/progress_medium_material</item>
+ <item>@drawable/progress_small_material</item>
+ <item>@drawable/quickcontact_badge_overlay_dark</item>
+ <item>@drawable/quickcontact_badge_overlay_light</item>
+ <item>@drawable/quickcontact_badge_overlay_normal_dark</item>
+ <item>@drawable/quickcontact_badge_overlay_normal_light</item>
+ <item>@drawable/quickcontact_badge_overlay_pressed_dark</item>
+ <item>@drawable/quickcontact_badge_overlay_pressed_light</item>
+ <item>@drawable/ratingbar_indicator_material</item>
+ <item>@drawable/ratingbar_material</item>
+ <item>@drawable/ratingbar_small_material</item>
+ <item>@drawable/screen_background_dark</item>
+ <item>@drawable/screen_background_dark_transparent</item>
+ <item>@drawable/screen_background_light</item>
+ <item>@drawable/screen_background_light_transparent</item>
+ <item>@drawable/screen_background_selector_dark</item>
+ <item>@drawable/screen_background_selector_light</item>
+ <item>@drawable/scrollbar_handle_material</item>
+ <item>@drawable/seekbar_thumb_material_anim</item>
+ <item>@drawable/seekbar_tick_mark_material</item>
+ <item>@drawable/seekbar_track_material</item>
+ <item>@drawable/spinner_background_material</item>
+ <item>@drawable/spinner_textfield_background_material</item>
+ <item>@drawable/switch_thumb_material_anim</item>
+ <item>@drawable/switch_track_material</item>
+ <item>@drawable/tab_indicator_material</item>
+ <item>@drawable/text_cursor_material</item>
+ <item>@drawable/text_edit_paste_window</item>
+ <item>@drawable/textfield_search_material</item>
+ <item>@drawable/text_select_handle_left_material</item>
+ <item>@drawable/text_select_handle_middle_material</item>
+ <item>@drawable/text_select_handle_right_material</item>
+ <item>@drawable/toast_frame</item>
</array>
<!-- Do not translate. These are all of the color state list resources that should be
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d12e34c..b61d6cf 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -593,9 +593,6 @@
the appearance matches the branding of the app requesting the fingerprint scan.-->
<attr name="fingerprintAuthDrawable" format="reference" />
- <!-- Asset that should be used to show users the position of the NFC antenna on the device. -->
- <attr name="nfcAntennaPositionDrawable" format="reference" />
-
<!-- ============ -->
<!-- Panel styles -->
<!-- ============ -->
@@ -4594,10 +4591,6 @@
screens with limited space for text. -->
<enum name="full" value="2" />
</attr>
- <!-- Placeholder for a deleted attribute. This should be removed before M release. -->
- <attr name="__removeBeforeMRelease_leftIndents" format="reference" />
- <!-- Placeholder for a deleted attribute. This should be removed before M release. -->
- <attr name="__removeBeforeMRelease_rightIndents" format="reference" />
</declare-styleable>
<declare-styleable name="TextViewAppearance">
<!-- Base text color, typeface, size, and style. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ad02d29..d0fd36a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2477,7 +2477,9 @@
remote provider -->
<string name="config_tvRemoteServicePackage" translatable="false"></string>
- <!-- True if the device supports persisting security logs across reboots. -->
+ <!-- True if the device supports persisting security logs across reboots.
+ This requires the device's kernel to have pstore and pmsg enabled,
+ and DRAM to be powered and refreshed through all stages of reboot. -->
<bool name="config_supportPreRebootSecurityLogs">false</bool>
<!-- Default files to pin via Pinner Service -->
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 573b066..37fb816 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -163,6 +163,9 @@
<!-- height of the content margin on the bottom -->
<dimen name="notification_content_margin_bottom">16dp</dimen>
+ <!-- The height of the background for a notification header on a group -->
+ <dimen name="notification_header_background_height">45.5dp</dimen>
+
<!-- Height of a small notification in the status bar -->
<dimen name="notification_min_height">92dp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 8e9e978..6797799 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2595,13 +2595,13 @@
<public type="attr" name="accessibilityTraversalAfter" id="0x010104d2" />
<public type="attr" name="dialogPreferredPadding" id="0x010104d3" />
<public type="attr" name="searchHintIcon" id="0x010104d4" />
- <public type="attr" name="revisionCode" />
- <public type="attr" name="drawableTint" />
- <public type="attr" name="drawableTintMode" />
- <public type="attr" name="fraction" />
+ <public type="attr" name="revisionCode" id="0x010104d5" />
+ <public type="attr" name="drawableTint" id="0x010104d6" />
+ <public type="attr" name="drawableTintMode" id="0x010104d7" />
+ <public type="attr" name="fraction" id="0x010104d8" />
- <public type="style" name="Theme.DeviceDefault.Dialog.Alert" />
- <public type="style" name="Theme.DeviceDefault.Light.Dialog.Alert" />
+ <public type="style" name="Theme.DeviceDefault.Dialog.Alert" id="0x010302d1" />
+ <public type="style" name="Theme.DeviceDefault.Light.Dialog.Alert" id="0x010302d2" />
<!-- ===============================================================
Resources added in version M of the platform
@@ -2653,83 +2653,79 @@
<public type="id" name="accessibilityActionScrollRight" id="0x0102003b" />
<public type="id" name="accessibilityActionContextClick" id="0x0102003c" />
- <public type="string" name="fingerprint_icon_content_description" />
+ <public type="string" name="fingerprint_icon_content_description" id="0x01040018" />
<!-- ===============================================================
Resources added in version N of the platform
=============================================================== -->
<eat-comment />
- <public type="attr" name="listMenuViewStyle" />
- <public type="attr" name="subMenuArrow" />
- <public type="attr" name="defaultWidth" />
- <public type="attr" name="defaultHeight" />
- <!-- @removed -->
- <public type="attr" name="minimalWidth" />
- <public type="attr" name="resizeableActivity" />
- <public type="attr" name="supportsPictureInPicture" />
- <public type="attr" name="titleMargin" />
- <public type="attr" name="titleMarginStart" />
- <public type="attr" name="titleMarginEnd" />
- <public type="attr" name="titleMarginTop" />
- <public type="attr" name="titleMarginBottom" />
- <public type="attr" name="maxButtonHeight" />
- <public type="attr" name="buttonGravity" />
- <public type="attr" name="collapseIcon" />
- <public type="attr" name="level" />
- <public type="attr" name="contextPopupMenuStyle" />
- <public type="attr" name="textAppearancePopupMenuHeader" />
- <public type="attr" name="windowBackgroundFallback" />
- <public type="attr" name="defaultToDeviceProtectedStorage" />
- <public type="attr" name="directBootAware" />
- <public type="attr" name="preferenceFragmentStyle" />
- <public type="attr" name="canControlMagnification" />
- <public type="attr" name="languageTag" />
- <public type="attr" name="pointerIcon" />
- <public type="attr" name="tickMark" />
- <public type="attr" name="tickMarkTint" />
- <public type="attr" name="tickMarkTintMode" />
- <public type="attr" name="canPerformGestures" />
- <public type="attr" name="externalService" />
- <public type="attr" name="supportsLocalInteraction" />
- <public type="attr" name="startX" />
- <public type="attr" name="startY" />
- <public type="attr" name="endX" />
- <public type="attr" name="endY" />
- <public type="attr" name="offset" />
- <public type="attr" name="use32bitAbi" />
- <public type="attr" name="bitmap" />
- <public type="attr" name="hotSpotX" />
- <public type="attr" name="hotSpotY" />
- <public type="attr" name="version" />
- <public type="attr" name="backupInForeground" />
- <public type="attr" name="countDown" />
- <public type="attr" name="canRecord" />
- <public type="attr" name="tunerCount" />
- <public type="attr" name="nfcAntennaPositionDrawable" />
- <public type="attr" name="fillType" />
- <public type="attr" name="popupEnterTransition" />
- <public type="attr" name="popupExitTransition" />
- <!-- @removed -->
- <public type="attr" name="minimalHeight" />
- <public type="attr" name="forceHasOverlappingRendering" />
- <public type="attr" name="contentInsetStartWithNavigation" />
- <public type="attr" name="contentInsetEndWithActions" />
- <public type="attr" name="numberPickerStyle" />
- <public type="attr" name="enableVrMode" />
- <public type="attr" name="hash" />
- <public type="attr" name="networkSecurityConfig" />
+ <public type="attr" name="listMenuViewStyle" id="0x010104f2" />
+ <public type="attr" name="subMenuArrow" id="0x010104f3" />
+ <public type="attr" name="defaultWidth" id="0x010104f4" />
+ <public type="attr" name="defaultHeight" id="0x010104f5" />
+ <public type="attr" name="resizeableActivity" id="0x010104f6" />
+ <public type="attr" name="supportsPictureInPicture" id="0x010104f7" />
+ <public type="attr" name="titleMargin" id="0x010104f8" />
+ <public type="attr" name="titleMarginStart" id="0x010104f9" />
+ <public type="attr" name="titleMarginEnd" id="0x010104fa" />
+ <public type="attr" name="titleMarginTop" id="0x010104fb" />
+ <public type="attr" name="titleMarginBottom" id="0x010104fc" />
+ <public type="attr" name="maxButtonHeight" id="0x010104fd" />
+ <public type="attr" name="buttonGravity" id="0x010104fe" />
+ <public type="attr" name="collapseIcon" id="0x010104ff" />
+ <public type="attr" name="level" id="0x01010500" />
+ <public type="attr" name="contextPopupMenuStyle" id="0x01010501" />
+ <public type="attr" name="textAppearancePopupMenuHeader" id="0x01010502" />
+ <public type="attr" name="windowBackgroundFallback" id="0x01010503" />
+ <public type="attr" name="defaultToDeviceProtectedStorage" id="0x01010504" />
+ <public type="attr" name="directBootAware" id="0x01010505" />
+ <public type="attr" name="preferenceFragmentStyle" id="0x01010506" />
+ <public type="attr" name="canControlMagnification" id="0x01010507" />
+ <public type="attr" name="languageTag" id="0x01010508" />
+ <public type="attr" name="pointerIcon" id="0x01010509" />
+ <public type="attr" name="tickMark" id="0x0101050a" />
+ <public type="attr" name="tickMarkTint" id="0x0101050b" />
+ <public type="attr" name="tickMarkTintMode" id="0x0101050c" />
+ <public type="attr" name="canPerformGestures" id="0x0101050d" />
+ <public type="attr" name="externalService" id="0x0101050e" />
+ <public type="attr" name="supportsLocalInteraction" id="0x0101050f" />
+ <public type="attr" name="startX" id="0x01010510" />
+ <public type="attr" name="startY" id="0x01010511" />
+ <public type="attr" name="endX" id="0x01010512" />
+ <public type="attr" name="endY" id="0x01010513" />
+ <public type="attr" name="offset" id="0x01010514" />
+ <public type="attr" name="use32bitAbi" id="0x01010515" />
+ <public type="attr" name="bitmap" id="0x01010516" />
+ <public type="attr" name="hotSpotX" id="0x01010517" />
+ <public type="attr" name="hotSpotY" id="0x01010518" />
+ <public type="attr" name="version" id="0x01010519" />
+ <public type="attr" name="backupInForeground" id="0x0101051a" />
+ <public type="attr" name="countDown" id="0x0101051b" />
+ <public type="attr" name="canRecord" id="0x0101051c" />
+ <public type="attr" name="tunerCount" id="0x0101051d" />
+ <public type="attr" name="fillType" id="0x0101051e" />
+ <public type="attr" name="popupEnterTransition" id="0x0101051f" />
+ <public type="attr" name="popupExitTransition" id="0x01010520" />
+ <public type="attr" name="forceHasOverlappingRendering" id="0x01010521" />
+ <public type="attr" name="contentInsetStartWithNavigation" id="0x01010522" />
+ <public type="attr" name="contentInsetEndWithActions" id="0x01010523" />
+ <public type="attr" name="numberPickerStyle" id="0x01010524" />
+ <public type="attr" name="enableVrMode" id="0x01010525" />
+ <public type="attr" name="hash" id="0x01010526" />
+ <public type="attr" name="networkSecurityConfig" id="0x01010527" />
- <public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
- <public type="style" name="Widget.Material.SeekBar.Discrete" />
- <public type="style" name="Widget.Material.CompoundButton.Switch" />
- <public type="style" name="Widget.Material.Light.CompoundButton.Switch" />
- <public type="style" name="Widget.Material.NumberPicker" />
- <public type="style" name="Widget.Material.Light.NumberPicker" />
+ <public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" id="0x010302d8" />
+ <public type="style" name="Widget.Material.SeekBar.Discrete" id="0x010302d9" />
+ <public type="style" name="Widget.Material.CompoundButton.Switch" id="0x010302da" />
+ <public type="style" name="Widget.Material.Light.CompoundButton.Switch" id="0x010302db" />
+ <public type="style" name="Widget.Material.NumberPicker" id="0x010302dc" />
+ <public type="style" name="Widget.Material.Light.NumberPicker" id="0x010302dd" />
+ <public type="style" name="TextAppearance.Material.Widget.Button.Colored" id="0x010302de" />
+ <public type="style" name="TextAppearance.Material.Widget.Button.Borderless.Colored" id="0x010302df" />
- <public type="id" name="accessibilityActionSetProgress" />
- <public type="id" name="icon_frame" />
- <public type="id" name="list_container" />
- <public type="id" name="switch_widget" />
-
+ <public type="id" name="accessibilityActionSetProgress" id="0x0102003d" />
+ <public type="id" name="icon_frame" id="0x0102003e" />
+ <public type="id" name="list_container" id="0x0102003f" />
+ <public type="id" name="switch_widget" id="0x01020040" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 45ee778..236940d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2474,6 +2474,54 @@
<item quantity="other">in <xliff:g example="2" id="count">%d</xliff:g>y</item>
</plurals>
+ <!-- Phrase describing a relative time using minutes in the past that is not shown on the screen but used for accessibility. [CHAR LIMIT=NONE] -->
+ <plurals name="duration_minutes_relative">
+ <item quantity="one"><xliff:g example="1" id="count">%d</xliff:g> minute ago</item>
+ <item quantity="other"><xliff:g example="2" id="count">%d</xliff:g> minutes ago</item>
+ </plurals>
+
+ <!-- Phrase describing a relative time using hours in the past that is not shown on the screen but used for accessibility. [CHAR LIMIT=NONE] -->
+ <plurals name="duration_hours_relative">
+ <item quantity="one"><xliff:g example="1" id="count">%d</xliff:g> hour ago</item>
+ <item quantity="other"><xliff:g example="2" id="count">%d</xliff:g> hours ago</item>
+ </plurals>
+
+ <!-- Phrase describing a relative time using days in the past that is not shown on the screen but used for accessibility. [CHAR LIMIT=NONE] -->
+ <plurals name="duration_days_relative">
+ <item quantity="one"><xliff:g example="1" id="count">%d</xliff:g> day ago</item>
+ <item quantity="other"><xliff:g example="2" id="count">%d</xliff:g> days ago</item>
+ </plurals>
+
+ <!-- Phrase describing a relative time using years in the past that is not shown on the screen but used for accessibility. [CHAR LIMIT=NONE] -->
+ <plurals name="duration_years_relative">
+ <item quantity="one"><xliff:g example="1" id="count">%d</xliff:g> year ago</item>
+ <item quantity="other"><xliff:g example="2" id="count">%d</xliff:g> years ago</item>
+ </plurals>
+
+ <!-- Phrase describing a relative time using minutes that is not shown on the screen but used for accessibility. This version should be a future point in time. [CHAR LIMIT=NONE] -->
+ <plurals name="duration_minutes_relative_future">
+ <item quantity="one">in <xliff:g example="1" id="count">%d</xliff:g> minute</item>
+ <item quantity="other">in <xliff:g example="2" id="count">%d</xliff:g> minutes</item>
+ </plurals>
+
+ <!-- Phrase describing a relative time using hours that is not shown on the screen but used for accessibility. This version should be a future point in time. [CHAR LIMIT=NONE] -->
+ <plurals name="duration_hours_relative_future">
+ <item quantity="one">in <xliff:g example="1" id="count">%d</xliff:g> hour</item>
+ <item quantity="other">in <xliff:g example="2" id="count">%d</xliff:g> hours</item>
+ </plurals>
+
+ <!-- Phrase describing a relative time using days that is not shown on the screen but used for accessibility. This version should be a future point in time. [CHAR LIMIT=NONE] -->
+ <plurals name="duration_days_relative_future">
+ <item quantity="one">in <xliff:g example="1" id="count">%d</xliff:g> day</item>
+ <item quantity="other">in <xliff:g example="2" id="count">%d</xliff:g> days</item>
+ </plurals>
+
+ <!-- Phrase describing a relative time using years that is not shown on the screen but used for accessibility. This version should be a future point in time. [CHAR LIMIT=NONE] -->
+ <plurals name="duration_years_relative_future">
+ <item quantity="one">in <xliff:g example="1" id="count">%d</xliff:g> year</item>
+ <item quantity="other">in <xliff:g example="2" id="count">%d</xliff:g> years</item>
+ </plurals>
+
<!-- Title for error alert when a video cannot be played. it can be used by any app. -->
<string name="VideoView_error_title">Video problem</string>
<!-- Text for error alert when a video container is not valid for progressive download/playback. -->
@@ -4081,8 +4129,6 @@
<!-- Notify use that they are in Lock-to-app -->
<string name="lock_to_app_toast">To unpin this screen, touch & hold Back.</string>
- <!-- Notify use that they are in Lock-to-app in accessibility mode -->
- <string name="lock_to_app_toast_accessible">To unpin this screen, touch & hold Overview.</string>
<!-- Notify user that they are locked in lock-to-app mode -->
<string name="lock_to_app_toast_locked">App is pinned: Unpinning isn\'t allowed on this device.</string>
<!-- Starting lock-to-app indication. -->
@@ -4215,6 +4261,12 @@
<!-- Content description of the work profile icon in the notification. -->
<string name="notification_work_profile_content_description">Work profile</string>
+ <!-- Content description of the expand button icon in the notification.-->
+ <string name="expand_button_content_description">Expand button</string>
+
+ <!-- Accessibility action description on the expand button. -->
+ <string name="expand_action_accessibility">Click to expand</string>
+
<!-- User visible name for USB MIDI Peripheral port -->
<string name="usb_midi_peripheral_name">Android USB Peripheral Port</string>
<!-- Manufacturer name for USB MIDI Peripheral port -->
@@ -4318,6 +4370,6 @@
<string name="audit_safemode_notification_details">Touch to learn more.</string>
<!-- Accessibilty string added to a widget that has been suspended [CHAR LIMIT=20] -->
- <string name="suspended_widget_accessibility">Suspended <xliff:g id="label" example="Calendar">%1$s</xliff:g></string>
+ <string name="suspended_widget_accessibility">Disabled <xliff:g id="label" example="Calendar">%1$s</xliff:g></string>
</resources>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 3ed8daa..bb07834 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -298,6 +298,14 @@
<item name="textColor">?attr/textColorPrimaryInverse</item>
</style>
+ <style name="TextAppearance.Material.Widget.Button.Colored">
+ <item name="textColor">@color/btn_colored_text_material</item>
+ </style>
+
+ <style name="TextAppearance.Material.Widget.Button.Borderless.Colored" parent="TextAppearance.Material.Widget.Button">
+ <item name="textColor">@color/btn_colored_borderless_text_material</item>
+ </style>
+
<style name="TextAppearance.Material.Widget.EditText">
<item name="textColor">?attr/textColorPrimaryInverse</item>
<item name="textColorHint">?attr/textColorHintInverse</item>
@@ -485,8 +493,7 @@
<!-- Colored bordered ink button -->
<style name="Widget.Material.Button.Colored">
<item name="background">@drawable/btn_colored_material</item>
- <item name="textAppearance">@style/TextAppearance.Material.Widget.Button.Inverse</item>
- <item name="textColor">@color/btn_colored_text_material</item>
+ <item name="textAppearance">@style/TextAppearance.Material.Widget.Button.Colored</item>
</style>
<!-- Small bordered ink button -->
@@ -503,7 +510,7 @@
<!-- Colored borderless ink button -->
<style name="Widget.Material.Button.Borderless.Colored">
- <item name="textColor">@color/btn_colored_borderless_text_material</item>
+ <item name="textAppearance">@style/TextAppearance.Material.Widget.Button.Borderless.Colored</item>
</style>
<!-- Alert dialog button bar button -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e99d57f..737daed 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -698,7 +698,6 @@
<java-symbol type="string" name="last_month" />
<java-symbol type="string" name="launchBrowserDefault" />
<java-symbol type="string" name="lock_to_app_toast" />
- <java-symbol type="string" name="lock_to_app_toast_accessible" />
<java-symbol type="string" name="lock_to_app_toast_locked" />
<java-symbol type="string" name="lock_to_app_start" />
<java-symbol type="string" name="lock_to_app_exit" />
@@ -2436,6 +2435,7 @@
<java-symbol type="dimen" name="notification_content_picture_margin" />
<java-symbol type="dimen" name="notification_content_margin_top" />
<java-symbol type="dimen" name="notification_content_margin_bottom" />
+ <java-symbol type="dimen" name="notification_header_background_height" />
<java-symbol type="string" name="importance_from_user" />
<java-symbol type="string" name="importance_from_person" />
@@ -2521,6 +2521,15 @@
<java-symbol type="plurals" name="duration_days_shortest_future" />
<java-symbol type="plurals" name="duration_years_shortest_future" />
+ <java-symbol type="plurals" name="duration_minutes_relative" />
+ <java-symbol type="plurals" name="duration_hours_relative" />
+ <java-symbol type="plurals" name="duration_days_relative" />
+ <java-symbol type="plurals" name="duration_years_relative" />
+ <java-symbol type="plurals" name="duration_minutes_relative_future" />
+ <java-symbol type="plurals" name="duration_hours_relative_future" />
+ <java-symbol type="plurals" name="duration_days_relative_future" />
+ <java-symbol type="plurals" name="duration_years_relative_future" />
+
<java-symbol type="string" name="now_string_shortest" />
<!-- Encryption notification while accounts are locked by credential encryption -->
diff --git a/core/tests/coretests/apks/locales/Android.mk b/core/tests/coretests/apks/locales/Android.mk
new file mode 100644
index 0000000..9cb13dd
--- /dev/null
+++ b/core/tests/coretests/apks/locales/Android.mk
@@ -0,0 +1,8 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := locales
+
+include $(FrameworkCoreTests_BUILD_PACKAGE)
diff --git a/core/tests/coretests/apks/locales/AndroidManifest.xml b/core/tests/coretests/apks/locales/AndroidManifest.xml
new file mode 100644
index 0000000..8a1f575
--- /dev/null
+++ b/core/tests/coretests/apks/locales/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.coretests.locales">
+
+ <application android:hasCode="false">
+ </application>
+</manifest>
diff --git a/core/tests/coretests/apks/locales/res/values-pl/values.xml b/core/tests/coretests/apks/locales/res/values-pl/values.xml
new file mode 100644
index 0000000..22237fa8
--- /dev/null
+++ b/core/tests/coretests/apks/locales/res/values-pl/values.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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>
+ <string name="text">Text (pl)</string>
+</resources>
diff --git a/core/tests/coretests/apks/locales/res/values/values.xml b/core/tests/coretests/apks/locales/res/values/values.xml
new file mode 100644
index 0000000..cb990d2
--- /dev/null
+++ b/core/tests/coretests/apks/locales/res/values/values.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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>
+ <string name="text">Text</string>
+</resources>
diff --git a/core/tests/coretests/src/android/content/res/ResourcesLocaleTest.java b/core/tests/coretests/src/android/content/res/ResourcesLocaleTest.java
new file mode 100644
index 0000000..e85666e
--- /dev/null
+++ b/core/tests/coretests/src/android/content/res/ResourcesLocaleTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2016 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.content.res;
+
+import android.os.FileUtils;
+import android.os.LocaleList;
+import android.support.test.filters.SmallTest;
+import android.test.AndroidTestCase;
+import android.util.DisplayMetrics;
+import android.view.Display;
+
+import com.android.frameworks.coretests.R;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Locale;
+
+public class ResourcesLocaleTest extends AndroidTestCase {
+
+ private String extractApkAndGetPath(int id) throws Exception {
+ final Resources resources = getContext().getResources();
+ try (InputStream is = resources.openRawResource(id)) {
+ File path = new File(getContext().getFilesDir(), resources.getResourceEntryName(id));
+ FileUtils.copyToFileOrThrow(is, path);
+ return path.getAbsolutePath();
+ }
+ }
+
+ private Resources createResourcesWithApk(int rawApkId) throws Exception {
+ final AssetManager assets = new AssetManager();
+ assertTrue(assets.addAssetPath(extractApkAndGetPath(rawApkId)) != 0);
+
+ final DisplayMetrics dm = new DisplayMetrics();
+ dm.setToDefaults();
+ return new Resources(assets, dm, new Configuration());
+ }
+
+ private static void ensureNoLanguage(Resources resources, String language) {
+ final String[] supportedLocales = resources.getAssets().getNonSystemLocales();
+ for (String languageTag : supportedLocales) {
+ if ("en-XA".equals(languageTag)) {
+ continue;
+ }
+ assertFalse(
+ "supported locales: " + Arrays.toString(supportedLocales),
+ language.equals(Locale.forLanguageTag(languageTag).getLanguage()));
+ }
+ }
+
+ @SmallTest
+ public void testEnglishIsAlwaysConsideredSupported() throws Exception {
+ final Resources resources = createResourcesWithApk(R.raw.locales);
+ ensureNoLanguage(resources, "en");
+
+ final LocaleList preferredLocales = LocaleList.forLanguageTags("en-US,pl-PL");
+ final Configuration config = new Configuration();
+ config.setLocales(preferredLocales);
+
+ resources.updateConfiguration(config, null);
+
+ // The APK we loaded has default and Polish languages. If English is first in the list,
+ // always take it the default (assumed to be English).
+ assertEquals(Locale.forLanguageTag("en-US"),
+ resources.getConfiguration().getLocales().get(0));
+ }
+
+ @SmallTest
+ public void testSelectFirstSupportedLanguage() throws Exception {
+ final Resources resources = createResourcesWithApk(R.raw.locales);
+ ensureNoLanguage(resources, "fr");
+
+ final LocaleList preferredLocales = LocaleList.forLanguageTags("fr-FR,pl-PL");
+ final Configuration config = new Configuration();
+ config.setLocales(preferredLocales);
+
+ resources.updateConfiguration(config, null);
+
+ // The APK we loaded has default and Polish languages. We expect the Polish language to
+ // therefore be chosen.
+ assertEquals(Locale.forLanguageTag("pl-PL"),
+ resources.getConfiguration().getLocales().get(0));
+ }
+}
diff --git a/docs/html-intl/intl/es/preview/setup-sdk.jd b/docs/html-intl/intl/es/preview/setup-sdk.jd
index 01c715b..39e84a8 100644
--- a/docs/html-intl/intl/es/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/es/preview/setup-sdk.jd
@@ -130,7 +130,7 @@
SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
</td>
</tr>
-<table>
+</table>
@@ -221,4 +221,3 @@
y <a href="{@docRoot}preview/api-overview.html">API y funciones de Android N
</a>.</li>
</ul>
-
diff --git a/docs/html-intl/intl/in/preview/setup-sdk.jd b/docs/html-intl/intl/in/preview/setup-sdk.jd
index a842931..2502d7d 100644
--- a/docs/html-intl/intl/in/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/in/preview/setup-sdk.jd
@@ -130,7 +130,7 @@
SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
</td>
</tr>
-<table>
+</table>
@@ -221,4 +221,3 @@
dan <a href="{@docRoot}preview/api-overview.html">Android N API
dan Fiturnya</a>.</li>
</ul>
-
diff --git a/docs/html-intl/intl/ja/preview/setup-sdk.jd b/docs/html-intl/intl/ja/preview/setup-sdk.jd
index fd5faba..36c2144 100644
--- a/docs/html-intl/intl/ja/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/ja/preview/setup-sdk.jd
@@ -130,7 +130,7 @@
SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
</td>
</tr>
-<table>
+</table>
@@ -221,4 +221,3 @@
</li>
</ul>
-
diff --git a/docs/html-intl/intl/ko/preview/setup-sdk.jd b/docs/html-intl/intl/ko/preview/setup-sdk.jd
index adb9edf..d04acef 100644
--- a/docs/html-intl/intl/ko/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/ko/preview/setup-sdk.jd
@@ -130,13 +130,13 @@
SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
</td>
</tr>
-<table>
+</table>
<h2 id="java8">Java 8 JDK 및 JRE 가져오기</h2>
-<p>Android N 플랫폼에 대해 앱을 컴파일하려면
+<p>Android N 플랫폼에 대해 앱을 컴파일하려면
Java 8 개발자 키트(JDK 8)를 사용해야 하며, Android
Studio 2.1의 일부 도구를 사용하려면 Java 8 런타임 환경(JRE 8)을 설치해야
합니다. 따라서 각각 최신 버전이 없는 경우, 지금 JDK 8 및 JRE 8를
@@ -221,4 +221,3 @@
및 기능</a>에서 Android N 플랫폼에
대해 자세히 알아봅니다.</li>
</ul>
-
diff --git a/docs/html-intl/intl/pt-br/preview/setup-sdk.jd b/docs/html-intl/intl/pt-br/preview/setup-sdk.jd
index 4159c25..a917da3 100644
--- a/docs/html-intl/intl/pt-br/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/pt-br/preview/setup-sdk.jd
@@ -79,7 +79,7 @@
<h2 id="get-sdk">Obter o N Preview SDK</h2>
-<p>Para começar a desenvolver com as APIs do Android N, instale o
+<p>Para começar a desenvolver com as APIs do Android N, instale o
Android N Preview SDK no Android Studio da seguinte maneira:</p>
<ol>
@@ -112,7 +112,7 @@
<p>
Informações detalhadas sobre as APIs do Android N são disponibilizadas na documentação de referência do N Preview
, que pode ser baixada pela tabela a seguir.
- Este pacote contém uma versão off-line resumida do site de desenvolvedores do Android
+ Este pacote contém uma versão off-line resumida do site de desenvolvedores do Android
e inclui uma referência atualizada para as APIs do Android N, além de um relatório
das diferenças entre as APIs.
</p>
@@ -130,7 +130,7 @@
SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
</td>
</tr>
-<table>
+</table>
@@ -168,7 +168,7 @@
Para usar as APIs do Android N, seu projeto deve ser configurado da maneira apropriada.
</p>
-<p>Se planeja usar os recursos de linguagem do Java 8, consulte
+<p>Se planeja usar os recursos de linguagem do Java 8, consulte
<a href="{@docRoot}preview/j8-jack.html">Recursos de linguagem do Java 8</a>
para saber mais sobre os recursos do Java 8 com suporte e
como configurar seu projeto com o compilador Jack.</p>
@@ -216,9 +216,8 @@
<ul>
<li>Siga o guia para <a href="{@docRoot}preview/download.html">Testar em um dispositivo Android N</a>.</li>
- <li>Saiba mais sobre a plataforma Android N com
+ <li>Saiba mais sobre a plataforma Android N com
<a href="{@docRoot}preview/behavior-changes.html">Mudanças de comportamento</a>
e <a href="{@docRoot}preview/api-overview.html">Recursos de APIs do
Android N</a>.</li>
</ul>
-
diff --git a/docs/html-intl/intl/ru/preview/setup-sdk.jd b/docs/html-intl/intl/ru/preview/setup-sdk.jd
index 3838700..6ae86e9 100644
--- a/docs/html-intl/intl/ru/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/ru/preview/setup-sdk.jd
@@ -79,7 +79,7 @@
<h2 id="get-sdk">Установка N Preview SDK</h2>
-<p>Чтобы начать разработку с использованием API-интерфейсов Android N, необходимо установить
+<p>Чтобы начать разработку с использованием API-интерфейсов Android N, необходимо установить
Android N Preview SDK в Android Studio, выполнив следующие шаги.</p>
<ol>
@@ -130,13 +130,13 @@
SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
</td>
</tr>
-<table>
+</table>
<h2 id="java8">Установка Java 8 JDK и JRE</h2>
-<p>Чтобы скомпилировать ваше приложение для платформы Android N, необходимо использовать
+<p>Чтобы скомпилировать ваше приложение для платформы Android N, необходимо использовать
Java 8 Developer Kit (JDK 8), а для использования некоторых инструментов с Android
Studio 2.1 необходимо установить Java 8 Runtime Environment (JRE 8). Поэтому если у вас еще
нет последних версий каждого из этих пакетов, загрузите JDK 8 и JRE 8
@@ -221,4 +221,3 @@
и в описании <a href="{@docRoot}preview/api-overview.html">API-интерфейсов и возможностей Android N</a>.
</li>
</ul>
-
diff --git a/docs/html-intl/intl/vi/preview/index.jd b/docs/html-intl/intl/vi/preview/index.jd
index 25289e0..bd64b25 100644
--- a/docs/html-intl/intl/vi/preview/index.jd
+++ b/docs/html-intl/intl/vi/preview/index.jd
@@ -31,7 +31,7 @@
<strong>thông báo trả lời trực tiếp</strong> và nhiều tính năng khác.
</p>
- <a href="http://factoryberlin.com" target="_new">
+ <a class="dac-hero-cta" href="{@docRoot}preview/overview.html">
<span class="dac-sprite dac-auto-chevron"></span>
Bắt đầu
</a><!--<br>
@@ -61,19 +61,19 @@
</a>
<ul class="dac-actions">
<li class="dac-action">
- <a href="http://factoryberlin.com" target="_new">
+ <a class="dac-action-link" href="https://developer.android.com/preview/bug">
<i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
Báo cáo vấn đề
</a>
</li>
<li class="dac-action">
- <a href="http://factoryberlin.com" target="_new">
+ <a class="dac-action-link" href="{@docRoot}preview/support.html">
<i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
Xem ghi chú phát hành
</a>
</li>
<li class="dac-action">
- <a href="http://factoryberlin.com" target="_new">
+ <a class="dac-action-link" href="{@docRoot}preview/dev-community">
<i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
Tham gia cộng đồng nhà phát triển
</a>
@@ -86,15 +86,15 @@
<div class="wrap dac-offset-parent">
<div class="actions">
- <div><a href="http://factoryberlin.com" target="_new">
+ <div><a href="https://developer.android.com/preview/bug">
<span class="dac-sprite dac-auto-chevron-large"></span>
Báo cáo vấn đề
</a></div>
- <div><a href="http://factoryberlin.com" target="_new">
+ <div><a href="{@docRoot}preview/support.html">
<span class="dac-sprite dac-auto-chevron-large"></span>
Xem ghi chú phát hành
</a></div>
- <div><a href="http://factoryberlin.com" target="_new">
+ <div><a href="{@docRoot}preview/dev-community">
<span class="dac-sprite dac-auto-chevron-large"></span>
Tham gia cộng đồng nhà phát triển
</a></div>
diff --git a/docs/html-intl/intl/vi/preview/setup-sdk.jd b/docs/html-intl/intl/vi/preview/setup-sdk.jd
index 2e3a18b..bdba713 100644
--- a/docs/html-intl/intl/vi/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/vi/preview/setup-sdk.jd
@@ -98,7 +98,7 @@
<li>Nhấp vào tab <strong>SDK Tools</strong>, rồi chọn
<strong>Android SDK Build Tools</strong>, <strong>Android SDK
- Platform-Tools</strong>, và các hộp kiểm <strong>Android SDK Tools</strong>
+ Platform-Tools</strong>, và các hộp kiểm <strong>Android SDK Tools</strong>
.
</li>
@@ -130,7 +130,7 @@
SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
</td>
</tr>
-<table>
+</table>
@@ -221,4 +221,3 @@
và<a href="{@docRoot}preview/api-overview.html">API Android N
và Các tính năng</a>.</li>
</ul>
-
diff --git a/docs/html-intl/intl/zh-cn/preview/setup-sdk.jd b/docs/html-intl/intl/zh-cn/preview/setup-sdk.jd
index 216d464..69971d8 100644
--- a/docs/html-intl/intl/zh-cn/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/zh-cn/preview/setup-sdk.jd
@@ -130,7 +130,7 @@
SHA-1:6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
</td>
</tr>
-<table>
+</table>
@@ -221,4 +221,3 @@
</li>
</ul>
-
diff --git a/docs/html-intl/intl/zh-tw/preview/setup-sdk.jd b/docs/html-intl/intl/zh-tw/preview/setup-sdk.jd
index d2a9d9e..b486ed4 100644
--- a/docs/html-intl/intl/zh-tw/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/zh-tw/preview/setup-sdk.jd
@@ -130,7 +130,7 @@
SHA-1:6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
</td>
</tr>
-<table>
+</table>
@@ -221,4 +221,3 @@
</li>
</ul>
-
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index 4211c6f..9e9343e 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -127,6 +127,8 @@
to: https://developers.google.com/mobile-ads-sdk/
- from: /google/play-services/wallet.html
to: https://developers.google.com/wallet/instant-buy/
+- from: /google/play-services/id.html
+ to: https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient
- from: /google/play/safetynet/...
to: /training/safetynet/index.html
- from: /google/gcm/...
@@ -843,6 +845,8 @@
to: /studio/run/emulator.html
- from: /r/studio-ui/instant-run.html
to: /studio/run/index.html#instant-run
+- from: /r/studio-ui/test-recorder.html
+ to: http://tools.android.com/tech-docs/test-recorder
- from: /reference/org/apache/http/...
to: /about/versions/marshmallow/android-6.0-changes.html#behavior-apache-http-client
- from: /shareables/...
diff --git a/docs/html/google/_book.yaml b/docs/html/google/_book.yaml
index 92357e9..885ad7a 100644
--- a/docs/html/google/_book.yaml
+++ b/docs/html/google/_book.yaml
@@ -63,9 +63,6 @@
- title: Google Play Developer API
path: /google/play/developer-api.html
-- title: Advertising ID
- path: /google/play-services/id.html
-
- title: Multiple APK Support
path: /google/play/publishing/multiple-apks.html
diff --git a/docs/html/google/play-services/id.jd b/docs/html/google/play-services/id.jd
deleted file mode 100644
index 2f0664c..0000000
--- a/docs/html/google/play-services/id.jd
+++ /dev/null
@@ -1,193 +0,0 @@
-page.title=Advertising ID
-page.tags=Ads,Advertising ID,ID
-
-@jd:body
-<div class="landing-banner">
-
-<div class="col-8">
-<p itemprop="description">
- The advertising ID is a user-specific, unique, resettable ID for advertising,
- provided by Google Play services. It gives users better controls and provides
- developers with a simple, standard system to continue to monetize your apps.
- It is an anonymous identifier for advertising purposes and enables users to
- reset their identifier or opt out of interest-based ads within Google Play
- apps.
-</p>
-<p>
- The advertising ID is accessible through a straightforward API that you can
- implement in your apps. For details, take a look at the <a href=
- "#get_started">overview</a> and the <a href=
- "https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/package-summary">
- advertising ID API reference</a>.
-</p>
-</div>
-</div>
-<div class="landing-docs">
- <div class="col-6 normal-links">
- <h3 style="clear:left">Key Developer Features</h3>
- <h4>Standard, simple ID</h4>
- <p>The advertising ID is a part of a standard, simple system for serving ads and performing analytics.</p>
- <h4>Giving users control</h4>
- <p>Users can reset their advertising ID or opt out of interest-based ads at any time, right from the Google Settings app.
- Their preferences apply across all ad companies that use the advertising ID.</p>
-
- </div>
- <div class="col-6 normal-links">
- <h3 style="clear:left">Getting Started</h3>
- <h4>1. Get the Google Play services SDK</h4>
- <p>The advertising ID APIs are part of the Google Play services platform.</p>
- <p>To get started, <a href="https://developers.google.com/android/guides/setup">set up
- the Google Play services SDK</a>. </p>
- <h4>2. Read the docs and example code</h4>
- <p>Once you've installed the Google Play services package, review the <a href="#get_started">overview</a>
- below, as well as the <a href="#example">example</a>.</p>
- <p>
- For detailed documentation, take a look at the <a href=
- "https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/package-summary">
- advertising ID API reference documentation</a>.
- </p>
- </div>
-</div>
-<p class="caution" style=
-"background-color:#fffdeb;width:100%;margin-bottom:1em;padding:.5em;">
- As a reminder, please note that starting <strong>1 August 2014</strong>, new
- apps and app updates distributed through Google Play must use the advertising
- ID in lieu of any other persistent identifiers for any advertising purposes,
- on devices that support the advertising ID.<br>
- <br>
- To learn how to check your app's compliance through the Developer Console, or
- for details on the associated developer policy changes, please see the
- <a href=
- "https://support.google.com/googleplay/android-developer/answer/6048248">Advertising
- ID topic</a> in the Google Play developer help center.
-</p>
-<h2 id="get_started">Using the Advertising ID</h2>
-<p>
- The <strong>advertising ID</strong> is a unique but
- user-resettable string identifier that lets ad networks and other apps anonymously
- identify a user. The user's advertising ID is made available to apps through APIs
- provided in Google Play services.
-</p>
-<p>
- Users can reset their advertising ID at any time, right from the Ads section of the
- Google Settings app on their devices. From the same app, users can also
- opt-out of targeted advertising based on the advertising ID by setting the appropriate
- <strong style="white-space:nowrap">ad tracking preference</strong>. When the
- user opts-out of targeted ads, this ad tracking preference is made available
- to apps through a Google Play services API.
-</p>
-<p>
- Apps making use of the advertising ID <strong>must check for and respect</strong> the
- user's ad tracking preference. Also please note that any use of the advertising ID
- must abide by the terms of the <a class="external-link"
- href="http://play.google.com/about/developer-content-policy.html#ADID">Google Play
- Developer Content Policies</a>.
-</p>
-<h3 id="format">Format of the Advertising ID</h3>
-<p>
- Google Play services APIs expose the user's advertising ID as a string format of UUID,
- with values similar to this:
-</p>
-<p style="margin-left:1.5em;"><code>"38400000-8cf0-11bd-b23e-10b96e40000d"</code></p>
-<h3 id="requirements">Requirements</h3>
-<ul>
- <li>The advertising ID APIs are supported in Google Play services 4.0+</li>
- <li>Support for the advertising ID on specific devices is based on their installed versions
- of Google Play services</li>
-</ul>
-<h3 id="obtaining">Obtaining the user's advertising ID and ad tracking preference</h3>
-<p>
- If you want to use the advertising ID in your app, you must first install the Google
- Play services SDK. As noted in the requirements above, you should install the
- SDK for Google Play services 4.0 or higher if you will develop using the advertising ID
- APIs. For information about how to get started, see <a href=
- "https://developers.google.com/android/guides/setup">Setting Up Google Play services</a>.
-</p>
-<p>
- The advertising ID APIs are available in the <a href=
- "{@docRoot}reference/com/google/android/gms/ads/identifier/package-summary.html">
- <code>com.google.android.gms.ads.identifier</code></a> package in the Google
- Play Services library. To obtain the user's advertising ID and tracking preference,
- call the method
- <a href=
- "{@docRoot}reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.html#getAdvertisingIdInfo(android.content.Context)">
- <code>getAdvertisingIdInfo()</code></a>, which returns an <a href=
- "{@docRoot}reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.Info.html">
- <code>AdvertisingIdClient.Info</code></a> encapsulating the user's current Advertising ID
- and tracking preference.
-</p>
-<p class="note">
- <strong>Note:</strong> The
- <a href=
- "{@docRoot}reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.html#getAdvertisingIdInfo(android.content.Context)"><code>getAdvertisingIdInfo()</code></a>
- method is a blocking call, so you must not call it on the main (UI) thread.
- If called on the main thread, the method throws
- {@link java.lang.IllegalStateException}.
-</p>
-<p>
- Once you've retrieved the
- <a href=
- "{@docRoot}reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.Info.html">
- <code>AdvertisingIdClient.Info</code></a>
- object, you can use its <a href=
- "{@docRoot}reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.Info.html#getId()">
- <code>getId()</code></a> and <a href=
- "{@docRoot}reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.Info.html#isLimitAdTrackingEnabled()">
- <code>isLimitAdTrackingEnabled()</code></a> methods to access the advertising ID and
- ad tracking preference.
-</p>
-<table>
-<tr>
-<th>Method</th>
-<th>Description</th>
-</tr>
-<tr>
-<td><code>public String <a href=
- "{@docRoot}reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.Info.html#getId()">getId()</a></code></td>
-<td style="white-space:nowrap;">Retrieves the advertising ID.</td>
-</tr>
-<tr>
-<td style="white-space:nowrap;"><code>public boolean <a href=
- "{@docRoot}reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.Info.html#isLimitAdTrackingEnabled()">isLimitAdTrackingEnabled()</a></code></td>
-<td>Retrieves whether the user has limit ad tracking enabled or not.</td>
-</tr>
-</table>
-<p>
- The advertising ID APIs do not include a "reset" method. Only users can initiate a
- reset of their own advertising IDs, through the Google Settings application.
-</p>
-<p>
- For more information about the advertising ID APIs, see the <a href=
- "{@docRoot}reference/com/google/android/gms/ads/identifier/package-summary.html">
- reference documentation</a>.
-</p>
-<h3 id="example">Example implementation</h3>
-<p>
- Here's a basic illustration of how you can retrieve the user's advertising ID and ad
- tracking preference in your app:
-</p>
-<pre>
-import com.google.android.gms.ads.identifier.AdvertisingIdClient;
-import com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;
-import com.google.android.gms.common.GooglePlayServicesAvailabilityException;
-import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
-import java.io.IOException;
-...
-// Do not call this function from the main thread. Otherwise,
-// an IllegalStateException will be thrown.
-public void getIdThread() {
- Info adInfo = null;
- try {
- adInfo = AdvertisingIdClient.getAdvertisingIdInfo(mContext.getApplicationContext());
- } catch (IOException e) {
- // Unrecoverable error connecting to Google Play services (e.g.,
- // the old version of the service doesn't support getting AdvertisingId).
-
- } catch (GooglePlayServicesAvailabilityException e) {
- // Encountered a recoverable error connecting to Google Play services.
- } catch (GooglePlayServicesNotAvailableException e) {
- // Google Play services is not available entirely.
- }
- final String id = adInfo.getId();
- final boolean isLAT = adInfo.isLimitAdTrackingEnabled();
-}</pre>
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
index b9d0082..5d163c0 100755
--- a/docs/html/guide/topics/manifest/uses-feature-element.jd
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -77,7 +77,7 @@
<p>The set of available features that your application declares corresponds to
the set of feature constants made available by the Android {@link
android.content.pm.PackageManager}, which are listed for
-convenience in the <a href="#features-reference">Features Reference</a> tables
+convenience in the <a href="#features-reference">Features Reference</a> sections
at the bottom of this document.
<p>You must specify each feature in a separate <code><uses-feature></code>
@@ -131,17 +131,27 @@
<dd>
<dl class="attr">
+ <dt>
+ <a name="name"></a><code>android:name</code>
+ </dt>
- <dt><a name="name"></a><code>android:name</code></dt>
- <dd>Specifies a single hardware or software feature used by the application,
-as a descriptor string. Valid descriptor values are listed in the <a
-href="#hw-features">Hardware features</a> and <a href="#sw-features">Software
-features</a> tables, below. Descriptor string values are case-sensitive.</dd>
+ <dd>
+ Specifies a single hardware or software feature used by the application, as
+ a descriptor string. Valid attribute values are listed in the <a href=
+ "#hw-features">Hardware features</a> and <a href="#sw-features">Software
+ features</a> sections. These attribute values are case-sensitive.
+ </dd>
- <dt><a name="required"></a><code>android:required</code></dt> <!-- added in api level 5 -->
- <dd>Boolean value that indicates whether the application requires
- the feature specified in <code>android:name</code>.
+ <dt>
+ <a name="required"></a><code>android:required</code>
+ </dt>
+ <!-- added in api level 5 -->
+ <dd>
+ Boolean value that indicates whether the application requires the feature
+ specified in <code>android:name</code>.
+ </dd>
+</dl>
<ul>
<li>When you declare <code>android:required="true"</code> for a feature,
you are specifying that the application <em>cannot function, or is not
@@ -163,7 +173,7 @@
<dd>The OpenGL ES version required by the application. The higher 16 bits
represent the major number and the lower 16 bits represent the minor number. For
example, to specify OpenGL ES version 2.0, you would set the value as
-"0x00020000", or to specify OpenGL ES 3.0, you would set the value as "0x00030000".
+"0x00020000", or to specify OpenGL ES 3.2, you would set the value as "0x00030002".
<p>An application should specify at most one <code>android:glEsVersion</code>
attribute in its manifest. If it specifies more than one, the
@@ -184,8 +194,8 @@
can check at run-time whether a higher level of OpenGL ES is available.)</p>
<p>For more information about using OpenGL ES, including how to check the supported OpenGL ES
-version at runtime, see the <a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL ES</a>
-API guide.</p>
+version at runtime, see the <a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL ES
+API guide</a>.</p>
</dd>
</dl>
@@ -229,7 +239,7 @@
<p>To ensure an accurate comparison of features, the Android Package Manager
provides a shared set of feature constants that both applications and devices
use to declare feature requirements and support. The available feature constants
-are listed in the <a href="#features-reference">Features Reference</a> tables at
+are listed in the <a href="#features-reference">Features Reference</a> sections at
the bottom of this document, and in the class documentation for {@link
android.content.pm.PackageManager}.</p>
@@ -362,8 +372,8 @@
<p class="caution">It's important to understand that the permissions that you
request in <code><uses-permission></code> elements can directly affect how
Google Play filters your application. The reference section <a
-href="#permissions">Permissions that Imply Feature Requirements</a>,
-below, lists the full set of permissions that imply feature requirements and
+href="#permissions">Permissions that Imply Feature Requirements</a> lists the
+full set of permissions that imply feature requirements and
therefore trigger filtering.</p>
<h3 id="bt-permission-handling">Special handling for Bluetooth feature</h3>
@@ -532,493 +542,1159 @@
densities: '160'
</pre>
+<h2 id="features-reference">
+ Features Reference
+</h2>
-<h2 id=features-reference>Features Reference</h2>
+<p>
+ The following sections provide reference information about hardware features,
+ software features, and sets of permissions that imply specific feature
+ requirements.
+</p>
-<p>The tables below provide reference information about hardware and software
-features and the permissions that can imply them on Google Play. </p>
+<h3 id="hw-features">
+ Hardware features
+</h3>
-<h3 id="hw-features">Hardware features</h3>
+<p>
+ This section presents the hardware features supported by the most current
+ platform release. To indicate that your app uses or requires a hardware
+ feature, declare the corresponding value (beginning with
+ <code>"android.hardware"</code>) in an <code>android:name</code> attribute.
+ Each time you declare a hardware feature, use a separate
+ <code><uses-feature></code> element.
+</p>
-<p>The table below describes the hardware feature descriptors supported by the
-most current platform release. To signal that your application uses or requires
-a hardware feature, declare each value in a <code>android:name</code> attribute
-in a separate <code><uses-feature></code> element. </p>
+<h4 id="audio-hw-features">
+ Audio hardware features
+</h4>
- <table>
- <tr>
- <th>Feature Type</th>
- <th>Feature Descriptor</th>
- <th style="min-width:170px">Description</th>
- <th>Comments</th>
- </tr>
- <tr>
- <td rowspan="4">Audio</td>
- <td><code>android.hardware.audio.low_latency</code></td>
- <td>The application uses a low-latency audio pipeline on the device and
- is sensitive to delays or lag in sound input or output.</td>
- <td></td>
- </tr>
- <tr>
- <td><code>android.hardware.audio.pro</code></td>
- <td>The application uses high-end audio functionality and performance.</td>
- <td></td>
- </tr>
- <tr>
- <td><code>android.hardware.microphone</code></td>
- <td>The application records audio via a microphone.</td>
- <td></td>
- </tr>
- </tr>
- <td><code>android.hardware.output</code></td>
- <td>The application produces at least one form of audio output, such as speakers, audio jack
- or streaming over bluetooth.</td>
- <td></td>
- </tr>
- <tr>
- <td rowspan="2">Bluetooth</td>
- <td><code>android.hardware.bluetooth</code></td>
- <td>The application uses Bluetooth radio features in the device.</td>
- <td></td>
- </tr>
- <tr>
- <td><code>android.hardware.bluetooth_le</code></td>
- <td>The application uses Bluetooth Low Energy radio features in the device.</td>
- <td></td>
- </tr>
- <tr>
- <td rowspan="6">Camera</td>
- <td><code>android.hardware.camera</code></td>
- <td>The application uses the device's back-facing (main) camera.</td>
- <td>Devices with only a front-facing camera do not list this feature, so
- the <code>android.hardware.camera.any</code> feature should be used
- instead if a camera facing any direction is acceptable for the
- application.</td>
- </tr>
-<tr>
- <td><code>android.hardware.camera.autofocus</code></td>
- <td>Subfeature. The application uses the device camera's autofocus capability.</td>
- <td rowspan="3">These subfeatures implicitly declare the
-<code>android.hardware.camera</code> parent feature, unless declared with
-<code>android:required="false"</code>.</td>
-</tr>
-<tr>
- <td><code>android.hardware.camera.flash</code></td>
- <td>Subfeature. The application uses the device camera's flash.</td>
-</tr>
-<tr>
- <td><code>android.hardware.camera.front</code></td>
- <td>Subfeature. The application uses a front-facing camera on the device.</td>
-</tr>
-<tr>
- <td><code>android.hardware.camera.any</code></td>
- <td>The application uses at least one camera facing in any direction, or an
-external camera device if one is connected. Use this in preference to
-<code>android.hardware.camera</code> if a back-facing camera is not required.
- </td>
-</tr>
-<tr>
- <td><code>android.hardware.camera.external</code></td>
- <td>The application uses an external camera device if one is connected.</td>
-</tr>
-<tr>
- <td><code>android.hardware.camera.level.full</code></td>
- <td>The application uses a camera device with <code>FULL</code>-level support.</td>
-</tr>
-<tr>
- <td><code>android.hardware.camera.capability.manual_sensor</code></td>
- <td>The application uses a a camera device with the <code>MANUAL_SENSOR</code> capability.</td>
-</tr>
-<tr>
- <td><code>android.hardware.camera.capability.manual_post_processing</code></td>
- <td>The application uses a a camera device with the <code>MANUAL_POST_PROCESSING</code> capability.</td>
-</tr>
-<tr>
- <td><code>android.hardware.camera.capability.raw</code></td>
- <td>The application uses a a camera device with the <code>RAW</code> capability.</td>
-</tr>
+<dl>
+ <dt>
+ <code>android.hardware.audio.low_latency</code>
+ </dt>
-<tr>
- <td>Infrared</td>
- <td><code>android.hardware.consumerir</code></td>
- <td>The application uses the consumer IR capabilities on the device.</td>
- <td></td>
-</tr>
+ <dd>
+ The app uses the device's low-latency audio pipeline, which reduces lag and
+ delays when processing sound input or output.
+ </dd>
-<tr>
- <td rowspan="3">Location</td>
- <td><code>android.hardware.location</code></td>
- <td>The application uses one or more features on the device for determining
-location, such as GPS location, network location, or cell location.</td>
- <td></td>
-</tr>
-<tr>
- <td><code>android.hardware.location.network</code></td>
- <td>Subfeature. The application uses coarse location coordinates obtained from
-a network-based geolocation system supported on the device.</td>
- <td rowspan="2">These subfeatures implicitly declare the
-<code>android.hardware.location</code> parent feature, unless declared with
-<code>android:required="false"</code>. </td>
-</tr>
-<tr>
- <td><code>android.hardware.location.gps</code></td>
- <td>Subfeature. The application uses precise location coordinates obtained
-from a Global Positioning System receiver on the device. </td>
-</tr>
-<tr>
- <td>Microphone</td>
- <td><code>android.hardware.microphone</code></td>
- <td>The application uses a microphone on the device.
- </td>
- <td></td>
-</tr>
-<tr>
- <td rowspan="2">NFC</td>
- <td><code>android.hardware.nfc</td>
- <td>The application uses Near Field Communications radio features in the device.</td>
- <td></td>
-</tr>
-<tr>
- <td><code>android.hardware.nfc.hce</code></td>
- <td>The application uses the NFC card emulation feature in the device.</td>
- <td></td>
-</tr>
-<tr>
- <td rowspan="8">Sensors</td>
- <td><code>android.hardware.sensor.accelerometer</code></td>
- <td>The application uses motion readings from an accelerometer on the
-device.</td>
- <td></td>
-</tr>
-<tr>
- <td><code>android.hardware.sensor.barometer</code></td>
- <td>The application uses the device's barometer.</td>
- <td></td>
-</tr>
-<tr>
- <td><code>android.hardware.sensor.compass</code></td>
- <td>The application uses directional readings from a magnetometer (compass) on
-the device.</td>
- <td></td>
-</tr>
-<tr>
- <td><code>android.hardware.sensor.gyroscope</code></td>
- <td>The application uses the device's gyroscope sensor.</td>
- <td></td>
-</tr>
-<tr>
- <td><code>android.hardware.sensor.light</code></td>
- <td>The application uses the device's light sensor.</td>
- <td></td>
-</tr>
-<tr>
- <td><code>android.hardware.sensor.proximity</code></td>
- <td>The application uses the device's proximity sensor.</td>
- <td></td>
-</tr>
-<tr>
- <td><code>android.hardware.sensor.stepcounter</code></td>
- <td>The application uses the device's step counter.</td>
- <td></td>
-</tr>
-<tr>
- <td><code>android.hardware.sensor.stepdetector</code></td>
- <td>The application uses the device's step detector.</td>
- <td></td>
-</tr>
+ <dt>
+ <code>android.hardware.audio.output</code>
+ </dt>
-<tr>
- <td rowspan="2">Screen</td>
- <td><code>android.hardware.screen.landscape</code></td>
- <td>The application requires landscape orientation.</td>
- <td rowspan="2">
- <p>For example, if your app requires portrait orientation, you should declare
-<code><uses-feature android:name="android.hardware.screen.portrait"/></code> so that only devices
-that support portrait orientation (whether always or by user choice) can install your app. If your
-application <em>supports</em> both orientations, then you don't need to declare either.</p>
- <p>Both orientations are assumed <em>not required</em>, by default, so your app may be installed
-on devices that support one or both orientations. However, if any of your activities request that
-they run in a specific orientation, using the <a
-href="{@docRoot}guide/topics/manifest/activity-element.html#screen">{@code
-android:screenOrientation}</a> attribute, then this also declares that the application requires that
-orientation. For example, if you declare <a
-href="{@docRoot}guide/topics/manifest/activity-element.html#screen">{@code
-android:screenOrientation}</a> with either {@code "landscape"}, {@code "reverseLandscape"}, or
-{@code "sensorLandscape"}, then your application will be available only to devices that support
-landscape orientation. As a best practice, you should still declare your requirement for this
-orientation using a {@code <uses-feature>} element. If you declare an orientation for your
-activity using <a href="{@docRoot}guide/topics/manifest/activity-element.html#screen">{@code
-android:screenOrientation}</a>, but don't actually <em>require</em> it, you can disable the
-requirement by declaring the orientation with a {@code <uses-feature>} element and include
-{@code android:required="false"}.</p>
- <p>For backwards compatibility, any device running a platform version that supports only API
-level 12 or lower is assumed to support both landscape and portrait.</p>
- </td>
-</tr>
-<tr>
- <td><code>android.hardware.screen.portrait</code></td>
- <td>The application requires portrait orientation.</td>
-</tr>
+ <dd>
+ The app transmits sound using the device's speakers, audio jack, Bluetooth
+ streaming capabilities, or a similar mechanism.
+ </dd>
-<tr>
- <td rowspan="3">Telephony</td>
- <td><code>android.hardware.telephony</code></td>
- <td>The application uses telephony features on the device, such as telephony
-radio with data communication services.</td>
- <td></td>
-</tr>
-<tr>
- <td><code>android.hardware.telephony.cdma</code></td>
- <td>Subfeature. The application uses CDMA telephony radio features on the
-device. </td>
- <td rowspan="2">These subfeatures implicitly declare the
-<code>android.hardware.telephony</code> parent feature, unless declared with
-<code>android:required="false"</code>. </td>
-</tr>
-<tr>
- <td><code>android.hardware.telephony.gsm</code></td>
- <td>Subfeature. The application uses GSM telephony radio features on the
-device.</td>
-</tr>
+ <dt>
+ <code>android.hardware.audio.pro</code>
+ </dt>
-<tr>
- <td>Television</td>
- <td><code>android.hardware.type.television</code></td>
- <td>The application is designed for a television user experience.</td>
- <td>This feature defines "television" to be a typical living room television experience:
- displayed on a big screen, where the user is sitting far away and the dominant form of
- input is something like a d-pad, and generally not through touch or a
- mouse/pointer-device.</td>
-</tr>
+ <dd>
+ The app uses the device's high-end audio functionality and performance
+ capabilities.
+ </dd>
-<tr>
- <td rowspan="7">Touchscreen</td>
- <td><code>android.hardware.faketouch</code></td>
- <td>The application uses basic touch interaction events, such as "click down", "click
-up", and drag.</td>
- <td><p>When declared as required, this indicates that the application is compatible with a device
-only if it offers an emulated touchscreen ("fake touch" interface), or better. A device that offers
-a fake touch interface provides a user input system that emulates a subset of touchscreen
-capabilities. For example, a mouse or remote control that drives an on-screen cursor provides a fake
-touch interface. If your application requires basic point and click interaction (in other
-words, it won't work with <em>only</em> a d-pad controller), you should declare this feature.
-Because this is the minimum level of touch interaction, your app will also be compatible with
-devices that offer more complex touch interfaces.</p>
- <p class="note"><strong>Note:</strong> Because applications require the {@code
-android.hardware.touchscreen} feature by default, if you want your application to be available to
-devices that provide a fake touch interface, you must also explicitly declare that a touch screen is
-<em>not</em> required by declaring <code><uses-feature
-android:name="android.hardware.touchscreen" <strong>android:required="false"</strong>
-/></code></p></td>
-</tr>
+ <dt>
+ <code>android.hardware.microphone</code>
+ </dt>
-<tr>
- <td><code>android.hardware.faketouch.multitouch.distinct</code></td>
- <td>The application performs distinct tracking of two or more "fingers" on a fake touch
-interface. This is a superset of the faketouch feature.</td>
- <td><p>When declared as required, this indicates that the application is compatible with a device
-only if it supports touch emulation for events that supports distinct tracking of two or more
-fingers, or better.</p>
- <p>Unlike the distinct multitouch defined by {@code
-android.hardware.touchscreen.multitouch.distinct}, input devices that support distinct multi-touch
-with a fake touch interface will not support all two-finger gestures, because the input is
-being transformed to cursor movement on the screen. That is, single finger gestures on such a device
-move a cursor; two-finger swipes will result in single-finger touch events; other two-finger
-gestures will result in the corresponding two-finger touch event. An example device that supports
-distinct multi-touch with a fake touch interface is one that provides a trackpad for cursor movement
-which also supports two or more fingers.</p></td>
-</tr>
+ <dd>
+ The app records audio using the device's microphone.
+ </dd>
+</dl>
-<tr>
- <td><code>android.hardware.faketouch.multitouch.jazzhand</code></td>
- <td>The application performs distinct tracking of five or more "fingers" on a fake touch
-interface. This is a superset of the faketouch feature.</td>
- <td><p>When declared as required, this indicates that the application is compatible with a device
-only if it supports touch emulation for events that supports distinct tracking of five or more
-fingers.</p>
- <p>Unlike the distinct multitouch defined by {@code
-android.hardware.touchscreen.multitouch.jazzhand}, input devices that support jazzhand multi-touch
-with a fake touch interface will not support all five-finger gestures, because the input is being
-transformed to cursor movement on the screen. That is, single finger gestures on such a device move
-a cursor; multi-finger gestures will result in single-finger touch events; other multi-finger
-gestures will result in the corresponding multi-finger touch event. An example device that supports
-distinct multi-touch with a fake touch interface is one that provides a trackpad for cursor movement
-which also supports five or more fingers.</p></td>
-</tr>
+<h4 id="bluetooth-hw-features">
+ Bluetooth hardware features
+</h4>
-<tr>
- <td><code>android.hardware.touchscreen</code></td>
- <td>The application uses touchscreen capabilities for gestures that are more interactive
-than basic touch events, such as a fling. This is a superset of the basic faketouch feature.</td>
- <td><p>By default, your application requires this. As such, your application is <em>not</em>
-available to devices that provide only an emulated touch interface ("fake touch"), by default. If
-you want your application available to devices that provide a fake touch interface (or even devices
-that provide only a d-pad controller), you must explicitly declare that a touch screen is not
-required, by declaring {@code android.hardware.touchscreen} with {@code android:required="false"}.
-You should do so even if your application uses—but does not <em>require</em>—a real
-touch screen interface.</p>
-<p>If your application <em>does require</em> a touch interface (in order to perform touch
-gestures such as a fling), then you don't need to do anything, because this is required by default.
-However, it's best if you explicitly declare all features used by your application, so you should
-still declare this if your app uses it.</p>
- <p>If you require more complex touch interaction, such as multi-finger gestures, you
-should declare the advanced touch screen features below.</p></td>
-</tr>
-<tr>
- <td><code>android.hardware.touchscreen.multitouch</code></td>
- <td>The application uses basic two-point multitouch capabilities on the device
-screen, such as for pinch gestures, but does not need to track touches independently. This
-is a superset of touchscreen feature.</td>
- <td>This implicitly declares the <code>android.hardware.touchscreen</code> parent feature, unless
-declared with <code>android:required="false"</code>. </td>
-</tr>
-<tr>
- <td><code>android.hardware.touchscreen.multitouch.distinct</code></td>
- <td>Subfeature. The application uses advanced multipoint multitouch
-capabilities on the device screen, such as for tracking two or more points fully
-independently. This is a superset of multitouch feature.</td>
- <td rowspan="2">This implicitly declares the <code>android.hardware.touchscreen.multitouch</code>
-parent feature, unless declared with <code>android:required="false"</code>. </td>
-</tr>
-<tr>
- <td><code>android.hardware.touchscreen.multitouch.jazzhand</code></td>
- <td>The application uses advanced multipoint multitouch
-capabilities on the device screen, for tracking up to five points fully
-independently. This is a superset of distinct multitouch feature.</td>
-</tr>
+<dl>
+ <dt>
+ <code>android.hardware.bluetooth</code>
+ </dt>
-<tr>
- <td rowspan="2">USB</td>
- <td><code>android.hardware.usb.host</code></td>
- <td>The application uses USB host mode features (behaves as the host and connects to USB
-devices).</td>
- <td></td>
-</tr>
+ <dd>
+ The app uses the device's Bluetooth features, usually to communicate with
+ other Bluetooth-enabled devices.
+ </dd>
-<tr>
- <td><code>android.hardware.usb.accessory</code></td>
- <td>The application uses USB accessory features (behaves as the USB device and connects to USB
-hosts).</td>
- <td></td>
-</tr>
+ <dt>
+ <code>android.hardware.bluetooth_le</code>
+ </dt>
-<tr>
- <td rowspan="2">Wi-Fi</td>
- <td><code>android.hardware.wifi</code></td>
- <td>The application uses 802.11 networking (Wi-Fi) features on the device.</td>
- <td></td>
-</tr>
-<tr>
- <td><code>android.hardware.wifi.direct</code></td>
- <td>The application uses the Wi-Fi Direct networking features on the device.</td>
-</tr>
+ <dd>
+ The app uses the device's Bluetooth Low Energy radio features.
+ </dd>
+</dl>
- </table>
+<h4 id="camera-hw-features">
+ Camera hardware features
+</h4>
-<h3 id="sw-features">Software features</h3>
+<dl>
+ <dt>
+ <code>android.hardware.camera</code>
+ </dt>
-<p>The table below describes the software feature descriptors supported by the
-most current platform release. To signal that your application uses or requires
-a software feature, declare each value in a <code>android:name</code> attribute
-in a separate <code><uses-feature></code> element. </p>
+ <dd>
+ The app uses the device's back-facing camera. Devices with only a
+ front-facing camera do not list this feature, so use the
+ <code>android.hardware.camera.any</code> feature instead if your app can
+ communicate with any camera, regardless of which direction the camera
+ faces.
+ </dd>
+ <dt>
+ <code>android.hardware.camera.any</code>
+ </dt>
- <table>
-<tr>
- <th>Feature</th>
- <th>Attribute Value</th>
- <th>Description</th>
-</tr>
-<tr>
- <td>App Widgets</td>
- <td><code>android.software.app_widgets</code></td>
- <td>The application uses or provides App Widgets and should be installed only on devices
- that include a Home screen or similar location where users can embed App Widgets.</td>
-</tr>
-<tr>
- <td>Device Management</td>
- <td><code>android.software.device_admin</code></td>
- <td>The application uses device policy enforcement via device administrators.</td>
-</tr>
-<tr>
- <td>Home Screen</td>
- <td><code>android.software.home_screen</code></td>
- <td>The application behaves as a Home screen replacement and should be installed only on
- devices that support third-party Home screen apps.</td>
-</tr>
-<tr>
- <td>Input Method</td>
- <td><code>android.software.input_methods</code></td>
- <td>The application provides a custom input method and should be installed only on devices that
- support third-party input methods.</td>
-</tr>
-<tr>
- <td>Live Wallpaper</td>
- <td><code>android.software.live_wallpaper</code></td>
- <td>The application uses or provides Live Wallpapers and should be installed only on devices that
- support Live Wallpapers.</td>
-</tr>
-<tr>
- <td>MIDI</td>
- <td><code>android.software.midi</code></td>
- <td>The application connects to musical instruments or outputs sound
- using the Musical Instrument Digital Interface (MIDI) protocol.</td>
-</tr>
-<tr>
- <td rowspan="2">SIP/VOIP</td>
- <td><code>android.software.sip</code></td>
- <td>The application uses SIP service on the device and should be installed only on devices that
- support SIP.
- </td>
-</tr>
-<tr>
- <td><code>android.software.sip.voip</code></td>
- <td><p>Subfeature. The application uses SIP-based VOIP service on the device.
- <p>This subfeature implicitly declares the <code>android.software.sip</code> parent feature,
-unless declared with <code>android:required="false"</code>.</td>
-</tr>
- </table>
+ <dd>
+ The app uses one of the device's cameras, or an external camera that the
+ user connects to the device. Use this value instead of
+ <code>android.hardware.camera</code> if your app does not require the
+ camera to be a back-facing one.
+ </dd>
+ <dt>
+ <code>android.hardware.camera.autofocus</code>
+ </dt>
-<h3 id="permissions">Permissions that Imply Feature Requirements</h3>
+ <dd>
+ <p>
+ The app uses the autofocus feature that the device's camera supports.
+ </p>
-<p>Some feature constants listed in the tables above were made available to
-applications <em>after</em> the corresponding API; for example, the
-<code>android.hardware.bluetooth</code> feature was added in Android 2.2 (API
-level 8), but the bluetooth API that it refers to was added in Android 2.0 (API
-level 5). Because of this, some apps were able to use the API before they had
-the ability to declare that they require the API via the
-<code><uses-feature></code> system. </p>
+ <p>
+ By using this feature, an app implies that it also uses the
+ <code>android.hardware.camera</code> feature, unless this parent feature
+ is declared with <code>android:required="false"</code>.
+ </p>
+ </dd>
-<p>To prevent those apps from being made available unintentionally, Google
-Play assumes that certain hardware-related permissions indicate that the
-underlying hardware features are required by default. For instance, applications
-that use Bluetooth must request the <code>BLUETOOTH</code> permission in a
-<code><uses-permission></code> element — for legacy apps, Google
-Play assumes that the permission declaration means that the underlying
-<code>android.hardware.bluetooth</code> feature is required by the application
-and sets up filtering based on that feature. </p>
+ <dt>
+ <code>android.hardware.camera.capability.manual_post_processing</code>
+ </dt>
-<p>The table below lists permissions that imply feature requirements
-equivalent to those declared in <code><uses-feature></code> elements. Note
-that <code><uses-feature></code> declarations, including any declared
-<code>android:required</code> attribute, always take precedence over features
-implied by the permissions below. </p>
+ <dd>
+ <p>
+ The app uses the <code>MANUAL_POST_PROCESSING</code> feature that the
+ device's camera supports.
+ </p>
-<p>For any of the permissions below, you can disable filtering based on the
-implied feature by explicitly declaring the implied feature explicitly, in a
-<code><uses-feature></code> element, with an
-<code>android:required="false"</code> attribute. For example, to disable any
-filtering based on the <code>CAMERA</code> permission, you would add this
-<code><uses-feature></code> declaration to the manifest file:</p>
+ <p>
+ This feature allows your app to override the camera's auto white balance
+ functionality. Use <code>android.colorCorrection.transform</code>,
+ <code>android.colorCorrection.gains</code>, and an
+ <code>android.colorCorrection.mode</code> of
+ <code>TRANSFORM_MATRIX</code>.
+ </p>
+ </dd>
+
+ <dt>
+ <code>android.hardware.camera.capability.manual_sensor</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app uses the <code>MANUAL_SENSOR</code> feature that the device's
+ camera supports.
+ </p>
+
+ <p>
+ This feature implies support for auto-exposure locking
+ (<code>android.control.aeLock</code>), which allows the camera's exposure
+ time and sensitivity to remain fixed at specific values.
+ </p>
+ </dd>
+
+ <dt>
+ <code>android.hardware.camera.capability.raw</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app uses the <code>RAW</code> feature that the device's camera
+ supports.
+ </p>
+
+ <p>
+ This feature implies that the device can save DNG (raw) files and that
+ the device's camera provides the DNG-related metadata necessary for your
+ app to process these raw images directly.
+ </p>
+ </dd>
+
+ <dt>
+ <code>android.hardware.camera.external</code>
+ </dt>
+
+ <dd>
+ The app communicates with an external camera that the user connects to the
+ device. This feature does not guarantee, however, that the external camera
+ is available for your app to use.
+ </dd>
+
+ <dt>
+ <code>android.hardware.camera.flash</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app uses the flash feature that the device's camera supports.
+ </p>
+
+ <p>
+ By using this feature, an app implies that it also uses the
+ <code>android.hardware.camera</code> feature, unless this parent feature
+ is declared with <code>android:required="false"</code>.
+ </p>
+ </dd>
+
+ <dt>
+ <code>android.hardware.camera.front</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app uses the device's front-facing camera.
+ </p>
+
+ <p>
+ By using this feature, an app implies that it also uses the
+ <code>android.hardware.camera</code> feature, unless this parent feature
+ is declared with <code>android:required="false"</code>.
+ </p>
+ </dd>
+
+ <dt>
+ <code>android.hardware.camera.level.full</code>
+ </dt>
+
+ <dd>
+ The app uses the <code>FULL</code>-level image-capturing support that at
+ least one of the device's cameras provides. Cameras with <code>FULL</code>
+ support provide burst-capture capabilities, per-frame control, and manual
+ post-processing control.
+ </dd>
+</dl>
+
+<h4 id="device-ui-hw-features">
+ Device UI hardware features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.hardware.type.automotive</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app is designed to show its UI on a set of screens inside a vehicle.
+ The user interacts with the app using hard buttons, touch, rotary
+ controllers, and mouse-like interfaces. The vehicle's screens usually
+ appear in the center console or the instrument cluster of a vehicle. These
+ screens usually have limited size and resolution.
+ </p>
+
+ <p class="note">
+ <strong>Note: </strong>It's important to keep in mind that, since the user
+ is driving while using this type of app UI, the app must minimize driver
+ distraction.
+ </p>
+ </dd>
+
+ <dt>
+ <code>android.hardware.type.television</code>
+ </dt>
+
+ <dd>
+ <p>
+ (Deprecated; use <a href="#media-sw-features">
+ <code>android.software.leanback</code></a> instead.)
+ </p>
+
+ <p>
+ The app is designed to show its UI on a television. This feature defines
+ "television" to be a typical living room television experience: displayed
+ on a big screen, where the user is sitting far away and the dominant form
+ of input is something like a d-pad, and generally not using a mouse,
+ pointer, or touch device.
+ </p>
+ </dd>
+
+ <dt>
+ <code>android.hardware.type.watch</code>
+ </dt>
+
+ <dd>
+ The app is designed to show its UI on a watch. A watch is worn on the body,
+ such as on the wrist. The user is very close to the device while
+ interacting with it.
+ </dd>
+</dl>
+
+<h4 id="fingerprint-hw-features">
+ Fingerprint hardware features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.hardware.fingerprint</code>
+ </dt>
+
+ <dd>
+ The app reads fingerprints using the device's biometric hardware.
+ </dd>
+</dl>
+
+<h4 id="gamepad-hw-features">
+ Gamepad hardware features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.hardware.gamepad</code>
+ </dt>
+
+ <dd>
+ The app captures game controller input, either from the device itself or
+ from a connected gamepad.
+ </dd>
+</dl>
+
+<h4 id="infrared-hw-features">
+ Infrared hardware features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.hardware.consumerir</code>
+ </dt>
+
+ <dd>
+ The app uses the device's infrared (IR) capabilities, usually to
+ communicate with other consumer IR devices.
+ </dd>
+</dl>
+
+<h4 id="location-hw-features">
+ Location hardware features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.hardware.location</code>
+ </dt>
+
+ <dd>
+ The app uses one or more features on the device for determining location,
+ such as GPS location, network location, or cell location.
+ </dd>
+
+ <dt>
+ <code>android.hardware.location.gps</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app uses precise location coordinates obtained from a Global
+ Positioning System (GPS) receiver on the device.
+ </p>
+
+ <p>
+ By using this feature, an app implies that it also uses the
+ <code>android.hardware.location</code> feature, unless this parent
+ feature is declared with the attribute
+ <code>android:required="false"</code>.
+ </p>
+ </dd>
+
+ <dt>
+ <code>android.hardware.location.network</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app uses coarse location coordinates obtained from a network-based
+ geolocation system supported on the device.
+ </p>
+
+ <p>
+ By using this feature, an app implies that it also uses the
+ <code>android.hardware.location</code> feature, unless this parent
+ feature is declared with the attribute
+ <code>android:required="false"</code>.
+ </p>
+ </dd>
+</dl>
+
+<h4 id="nfc-hw-features">
+ NFC hardware features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.hardware.nfc</code>
+ </dt>
+
+ <dd>
+ The app uses the device's Near-Field Communication (NFC) radio features.
+ </dd>
+
+ <dt>
+ <code>android.hardware.nfc.hce</code>
+ </dt>
+
+ <dd>
+ <p>
+ (Deprecated.)
+ </p>
+
+ <p>
+ The app uses NFC card emulation that is hosted on the device.
+ </p>
+ </dd>
+</dl>
+
+<h4 id="opengl-es-hw-features">
+ OpenGL ES hardware features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.hardware.opengles.aep</code>
+ </dt>
+
+ <dd>
+ The app uses the <a href=
+ "http://www.khronos.org/registry/gles/extensions/ANDROID/ANDROID_extension_pack_es31a.txt"
+ class="external-link">OpenGL ES Android Extension Pack</a>that is installed
+ on the device.
+ </dd>
+</dl>
+
+<h4 id="sensor-hw-features">
+ Sensor hardware features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.hardware.sensor.accelerometer</code>
+ </dt>
+
+ <dd>
+ The app uses motion readings from the device's accelerometer to detect
+ the device's current orientation. For example, an app could use
+ accelerometer readings to determine when to switch between portrait and
+ landscape orientations.
+ </dd>
+
+ <dt>
+ <code>android.hardware.sensor.ambient_temperature</code>
+ </dt>
+
+ <dd>
+ The app uses the device's ambient (environmental) temperature sensor. For
+ example, a weather app could report indoor or outdoor temperature.
+ </dd>
+
+ <dt>
+ <code>android.hardware.sensor.barometer</code>
+ </dt>
+
+ <dd>
+ The app uses the device's barometer. For example, a weather app could
+ report air pressure.
+ </dd>
+
+ <dt>
+ <code>android.hardware.sensor.compass</code>
+ </dt>
+
+ <dd>
+ The app uses the device's magnetometer (compass). For example, a navigation
+ app could show the current direction a user faces.
+ </dd>
+
+ <dt>
+ <code>android.hardware.sensor.gyroscope</code>
+ </dt>
+
+ <dd>
+ The app uses the device's gyroscope to detect rotation and twist, creating
+ a six-axis orientation system. By using this sensor, an app can detect more
+ smoothly whether it needs to switch between portrait and landscape
+ orientations.
+ </dd>
+
+ <dt>
+ <code>android.hardware.sensor.hifi_sensors</code>
+ </dt>
+
+ <dd>
+ The app uses the device's high fidelity (Hi-Fi) sensors. For example, a
+ gaming app could detect the user's high-precision movements.
+ </dd>
+
+ <dt>
+ <code>android.hardware.sensor.heartrate</code>
+ </dt>
+
+ <dd>
+ The app uses the device's heart rate monitor. For example, a fitness app
+ could report trends in a user's heart rate over time.
+ </dd>
+
+ <dt>
+ <code>android.hardware.sensor.heartrate.ecg</code>
+ </dt>
+
+ <dd>
+ The app uses the device's elcardiogram (ECG) heart rate sensor. For
+ example, a fitness app could report more detailed information about a
+ user's heart rate.
+ </dd>
+
+ <dt>
+ <code>android.hardware.sensor.light</code>
+ </dt>
+
+ <dd>
+ The app uses the device's light sensor. For example, an app could display
+ one of two different color schemes based on the ambient lighting
+ conditions.
+ </dd>
+
+ <dt>
+ <code>android.hardware.sensor.proximity</code>
+ </dt>
+
+ <dd>
+ The app uses the device's proximity sensor. For example, a telephony app
+ could turn off the device's screen when the app detects that the user is
+ holding the device close to their body.
+ </dd>
+
+ <dt>
+ <code>android.hardware.sensor.relative_humidity</code>
+ </dt>
+
+ <dd>
+ The app uses the device's relative humidity sensor. For example, a weather
+ app could use the humidity to calculate and report the current dewpoint.
+ </dd>
+
+ <dt>
+ <code>android.hardware.sensor.stepcounter</code>
+ </dt>
+
+ <dd>
+ The app uses the device's step counter. For example, a fitness app could
+ report the number of steps a user needs to take to achieve their daily step
+ count goal.
+ </dd>
+
+ <dt>
+ <code>android.hardware.sensor.stepdetector</code>
+ </dt>
+
+ <dd>
+ The app uses the device's step detector. For example, a fitness app could
+ use the time interval between steps to infer the type of exercise that the
+ user is doing.
+ </dd>
+</dl>
+
+<h4 id="screen-hw-features">
+ Screen hardware features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.hardware.screen.landscape</code>
+ </dt>
+
+ <dt>
+ <code>android.hardware.screen.portrait</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app requires the device to use the portrait or landscape orientation.
+ If your app supports both orientations, then you don't need to declare
+ either feature.
+ </p>
+
+ <p>
+ For example, if your app requires portrait orientation, you should
+ declare the following feature so that only the devices that support
+ portrait orientation (always or by user choice) can run your app:
+ </p>
+ <pre><uses-feature android:name="android.hardware.screen.portrait" /></pre>
+
+ <p>
+ Both orientations are assumed not required by default, so your app may be
+ installed on devices that support one or both orientations. However, if
+ any of your activities request that they run in a specific orientation,
+ using the <a href=
+ "{@docRoot}guide/topics/manifest/activity-element.html#screen">{@code
+ android:screenOrientation}</a> attribute, then this declaration implies
+ that your app requires that orientation. For example, if you declare
+ <a href=
+ "{@docRoot}guide/topics/manifest/activity-element.html#screen">{@code
+ android:screenOrientation}</a> with either {@code "landscape"}, {@code
+ "reverseLandscape"}, or {@code "sensorLandscape"}, then your app will be
+ available only on devices that support landscape orientation.
+ </p>
+
+ <p>
+ As a best practice, you should still declare your requirement for this
+ orientation using a {@code <uses-feature>} element. If you declare
+ an orientation for your activity using <a href=
+ "{@docRoot}guide/topics/manifest/activity-element.html#screen">{@code
+ android:screenOrientation}</a>, but don't actually require it, you can
+ disable the requirement by declaring the orientation with a {@code
+ <uses-feature>} element and include {@code
+ android:required="false"}.
+ </p>
+
+ <p>
+ For backward compatibility, any device running Android 3.1 (API level 12)
+ or lower supports both landscape and portrait orientations.
+ </p>
+ </dd>
+</dl>
+
+<h4 id="telephony-hw-features">
+ Telephony hardware features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.hardware.telephony</code>
+ </dt>
+
+ <dd>
+ The app uses the device's telephony features, such as telephony radio with
+ data communication services.
+ </dd>
+
+ <dt>
+ <code>android.hardware.telephony.cdma</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app uses the Code Division Multiple Access (CDMA) telephony radio
+ system.
+ </p>
+
+ <p>
+ By using this feature, an app implies that it also uses the
+ <code>android.hardware.telephony</code> feature, unless this parent
+ feature is declared with <code>android:required="false"</code>.
+ </p>
+ </dd>
+
+ <dt>
+ <code>android.hardware.telephony.gsm</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app uses the Global System for Mobile Communications (GSM) telephony
+ radio system.
+ </p>
+
+ <p>
+ By using this feature, an app implies that it also uses the
+ <code>android.hardware.telephony</code> feature, unless this parent
+ feature is declared with <code>android:required="false"</code>.
+ </p>
+ </dd>
+</dl>
+
+<h4 id="touchscreen-hw-features">
+ Touchscreen hardware features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.hardware.faketouch</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app uses basic touch interaction events, such as tapping and
+ dragging.
+ </p>
+
+ <p>
+ When declared as required, this feature indicates that the app is
+ compatible with a device only if that device emulates a touchscreen
+ ("fake touch" interface) or has an actual touchscreen.
+ </p>
+
+ <p>
+ A device that offers a fake touch interface provides a user input system
+ that emulates a subset of a touchscreen's capabilities. For example, a
+ mouse or remote control could drive an on-screen cursor. If your app
+ requires basic point and click interaction (in other words, it won't work
+ with only a d-pad controller), you should declare this feature. Because
+ this is the minimum level of touch interaction, you can also use an app
+ that declares this feature on devices that offer more complex touch
+ interfaces.
+ </p>
+
+ <p class="note">
+ <strong>Note:</strong> Apps require the {@code android.hardware.touchscreen}
+ feature by default. If you want your app to be available to devices that
+ provide a fake touch interface, you must also explicitly declare that a
+ touchscreen is not required as follows:
+ </p>
+ <pre><uses-feature android:name="android.hardware.touchscreen" <strong>android:required="false"</strong> /></pre>
+ </dd>
+
+ <dt>
+ <code>android.hardware.faketouch.multitouch.distinct</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app tracks two or more distinct "fingers" on a fake touch interface.
+ This is a superset of the <code>android.hardware.faketouch</code>
+ feature. When declared as required, this feature indicates that the app
+ is compatible with a device only if that device emulates distinct
+ tracking of two or more fingers or has an actual touchscreen.
+ </p>
+
+ <p>
+ Unlike the distinct multitouch defined by {@code
+ android.hardware.touchscreen.multitouch.distinct}, input devices that
+ support distinct multitouch with a fake touch interface don't support all
+ two-finger gestures because the input in transformed to cursor movement
+ on the screen. That is, single-finger gestures on such a device move a
+ cursor, two-finger swipes cause single-finger touch events to occur, and
+ other two-finger gestures trigger the corresponding two-finger touch
+ events.
+ </p>
+
+ <p>
+ A device that provides a two-finger touch trackpad for cursor movement
+ can support this feature.
+ </p>
+ </dd>
+
+ <dt>
+ <code>android.hardware.faketouch.multitouch.jazzhand</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app tracks five or more distinct "fingers" on a fake touch interface.
+ This is a superset of the <code>android.hardware.faketouch</code>
+ feature. When declared as required, this feature indicates that the app
+ is compatible with a device only if that device emulates distinct
+ tracking of five or more fingers or has an actual touchscreen.
+ </p>
+
+ <p>
+ Unlike the distinct multitouch defined by {@code
+ android.hardware.touchscreen.multitouch.jazzhand}, input devices that
+ support jazzhand multitouch with a fake touch interface don't support all
+ five-finger gestures because the input in transformed to cursor movement
+ on the screen. That is, single-finger gestures on such a device move a
+ cursor, multi-finger gestures cause single-finger touch events to occur,
+ and other multi-finger gestures trigger the corresponding multi-finger
+ touch events.
+ </p>
+
+ <p>
+ A device that provides a five-finger touch trackpad for cursor movement
+ can support this feature.
+ </p>
+ </dd>
+
+ <dt>
+ <code>android.hardware.touchscreen</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app uses the device's touchscreen capabilities for gestures that are
+ more interactive than basic touch events, such as a fling. This is a
+ superset of the <code>android.hardware.faketouch</code> feature.
+ </p>
+
+ <p>
+ By default, your app requires this feature. As such, your app is not
+ available to devices that provide only an emulated touch interface ("fake
+ touch") by default. If you want to make your app available on devices
+ that provide a fake touch interface (or even on devices that provide only
+ a d-pad controller), you must explicitly declare that a touchscreen is
+ not required by declaring {@code android.hardware.touchscreen} with
+ {@code android:required="false"}. You should add this declaration if your
+ app uses—but does not require—a real touchscreen interface.
+ </p>
+
+ <p>
+ If your app in fact requires a touch interface (to perform more advanced
+ touch gestures such as fling), then you don't need to declare any touch
+ interface features because they're required by default. However, it's
+ best if you explicitly declare all features that your app uses.
+ </p>
+
+ <p>
+ If you require more complex touch interaction, such as multi-finger
+ gestures, you should declare that your app uses advanced touchscreen
+ features.
+ </p>
+ </dd>
+
+ <dt>
+ <code>android.hardware.touchscreen.multitouch</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app uses the device's basic two-point multitouch capabilities, such
+ as for pinch gestures, but the app does not need to track touches
+ independently. This is a superset of the
+ <code>android.hardware.touchscreen</code> feature.
+ </p>
+
+ <p>
+ By using this feature, an app implies that it also uses the
+ <code>android.hardware.touchscreen</code> feature, unless this parent
+ feature is declared with <code>android:required="false"</code>.
+ </p>
+ </dd>
+
+ <dt>
+ <code>android.hardware.touchscreen.multitouch.distinct</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app uses the device's advanced multitouch capabilities for tracking
+ two or more points independently. This feature is a superset of the
+ <code>android.hardware.touchscreen.multitouch</code> feature.
+ </p>
+
+ <p>
+ By using this feature, an app implies that it also uses the
+ <code>android.hardware.touchscreen.multitouch</code> feature, unless this
+ parent feature is declared with <code>android:required="false"</code>.
+ </p>
+ </dd>
+
+ <dt>
+ <code>android.hardware.touchscreen.multitouch.jazzhand</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app uses the device's advanced multitouch capabilities for tracking
+ five or more points independently. This feature is a superset of the
+ <code>android.hardware.touchscreen.multitouch</code> feature.
+ </p>
+
+ <p>
+ By using this feature, an app implies that it also uses the
+ <code>android.hardware.touchscreen.multitouch</code> feature, unless this
+ parent feature is declared with <code>android:required="false"</code>.
+ </p>
+ </dd>
+</dl>
+
+<h4 id="usb-hw-features">
+ USB hardware features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.hardware.usb.accessory</code>
+ </dt>
+
+ <dd>
+ The app behaves as the USB device and connects to USB hosts.
+ </dd>
+
+ <dt>
+ <code>android.hardware.usb.host</code>
+ </dt>
+
+ <dd>
+ The app uses the USB accessories that are connected to the device. The
+ device serves as the USB host.
+ </dd>
+</dl>
+
+<h4 id="wi-fi-hw-features">
+ Wi-Fi hardware features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.hardware.wifi</code>
+ </dt>
+
+ <dd>
+ The app uses 802.11 networking (Wi-Fi) features on the device.
+ </dd>
+
+ <dt>
+ <code>android.hardware.wifi.direct</code>
+ </dt>
+
+ <dd>
+ The app uses the Wi-Fi Direct networking features on the device.
+ </dd>
+</dl>
+
+<h3 id="sw-features">
+ Software features
+</h3>
+
+<p>
+ This section presents the software features supported by the most current
+ platform release. To indicate that your app uses or requires a software
+ feature, declare the corresponding value (beginning with
+ <code>"android.software"</code>) in an <code>android:name</code> attribute.
+ Each time you declare a software feature, use a separate
+ <code><uses-feature></code> element.
+</p>
+
+<h4 id="communication-sw-features">
+ Communication software features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.software.sip</code>
+ </dt>
+
+ <dd>
+ The app uses Session Initiation Protocol (SIP) services. By using SIP, the
+ app can support internet telephony operations, such as video conferencing
+ and instant messaging.
+ </dd>
+
+ <dt>
+ <code>android.software.sip.voip</code>
+ </dt>
+
+ <dd>
+ <p>
+ The app uses SIP-based Voice Over Internet Protocol (VoIP) services. By
+ using VoIP, the app can support real-time internet telephony operations,
+ such as two-way video conferencing.
+ </p>
+
+ <p>
+ By using this feature, an app implies that it also uses the
+ <code>android.software.sip</code> feature, unless this parent feature is
+ declared with <code>android:required="false"</code>.
+ </p>
+ </dd>
+
+ <dt>
+ <code>android.software.webview</code>
+ </dt>
+
+ <dd>
+ The app displays content from the internet.
+ </dd>
+</dl>
+
+<h4 id="custom-input-sw-features">
+ Custom input software features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.software.input_methods</code>
+ </dt>
+
+ <dd>
+ The app uses a new input method, which the developer defines in an <a href=
+ "{@docRoot}reference/android/inputmethodservice/InputMethodService.html">{@code
+ InputMethodService}</a>.
+ </dd>
+</dl>
+
+<h4 id="device-management-sw-features">
+ Device management software features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.software.backup</code>
+ </dt>
+
+ <dd>
+ The app includes logic to handle a backup and restore operation.
+ </dd>
+
+ <dt>
+ <code>android.software.device_admin</code>
+ </dt>
+
+ <dd>
+ The app uses device administrators to enforce a device policy.
+ </dd>
+
+ <dt>
+ <code>android.software.managed_users</code>
+ </dt>
+
+ <dd>
+ The app supports secondary users and managed profiles.
+ </dd>
+
+ <dt>
+ <code>android.software.securely_removes_users</code>
+ </dt>
+
+ <dd>
+ The app can <strong>permanently</strong> remove users and their associated
+ data.
+ </dd>
+
+ <dt>
+ <code>android.software.verified_boot</code>
+ </dt>
+
+ <dd>
+ The app includes logic to handle results from the device's verified boot
+ feature, which detects whether the device's configuration changes during a
+ restart operation.
+ </dd>
+</dl>
+
+<h4 id="media-sw-features">
+ Media software features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.software.midi</code>
+ </dt>
+
+ <dd>
+ The app connects to musical instruments or outputs sound using the Musical
+ Instrument Digital Interface (MIDI) protocol.
+ </dd>
+
+ <dt>
+ <code>android.software.print</code>
+ </dt>
+
+ <dd>
+ The app includes commands for printing documents displayed on the device.
+ </dd>
+
+ <dt>
+ <code>android.software.leanback</code>
+ </dt>
+
+ <dd>
+ The app presents a UI that is designed for viewing on a large screen, such
+ as a television.
+ </dd>
+
+ <dt>
+ <code>android.software.live_tv</code>
+ </dt>
+
+ <dd>
+ The app streams live television programs.
+ </dd>
+</dl>
+
+<h4 id="screen-interface-sw-features">
+ Screen interface software features
+</h4>
+
+<dl>
+ <dt>
+ <code>android.software.app_widgets</code>
+ </dt>
+
+ <dd>
+ The app uses or provides App Widgets and should be installed only on
+ devices that include a Home screen or similar location where users can
+ embed App Widgets.
+ </dd>
+
+ <dt>
+ <code>android.software.home_screen</code>
+ </dt>
+
+ <dd>
+ The app behaves as a replacement to the device's Home screen.
+ </dd>
+
+ <dt>
+ <code>android.software.live_wallpaper</code>
+ </dt>
+
+ <dd>
+ The app uses or provides wallpapers that include animation.
+ </dd>
+</dl>
+
+<h3 id="permissions">
+ Permissions that Imply Feature Requirements
+</h3>
+
+<p>
+ Some of the hardware and software feature constants were made available to
+ applications after the corresponding API; for example, the
+ <code>android.hardware.bluetooth</code> feature was added in Android 2.2 (API
+ level 8), but the Bluetooth API that it refers to was added in Android 2.0
+ (API level 5). Because of this, some apps were able to use the API before
+ they had the ability to declare that they require the API using the
+ <code><uses-feature></code> system.
+</p>
+
+<p>
+ To prevent those apps from being made available unintentionally, Google Play
+ assumes that certain hardware-related permissions indicate that the
+ underlying hardware features are required by default. For instance,
+ applications that use Bluetooth must request the <code>BLUETOOTH</code>
+ permission in a <code><uses-permission></code> element — for legacy
+ apps, Google Play assumes that the permission declaration means that the
+ underlying <code>android.hardware.bluetooth</code> feature is required by the
+ application and sets up filtering based on that feature. Table 2 lists
+ permissions that imply feature requirements equivalent to those declared in
+ <code><uses-feature></code> elements.
+</p>
+
+<p>
+ Note that <code><uses-feature></code> declarations, including any
+ declared <code>android:required</code> attribute, always take precedence over
+ features implied by the permissions in table 2. For any of these permissions,
+ you can disable filtering based on the implied feature by explicitly
+ declaring the implied feature explicitly, in a
+ <code><uses-feature></code> element, with an
+ <code>android:required="false"</code> attribute. For example, to disable any
+ filtering based on the <code>CAMERA</code> permission, you would add this
+ <code><uses-feature></code> declaration to the manifest file:
+</p>
<pre><uses-feature android:name="android.hardware.camera" android:required="false" /></pre>
-<table id="permissions-features" >
+<p class="table-caption" id="permissions-features">
+ <strong>Table 2. </strong>Device permissions that imply device hardware use.
+</p>
+<table>
<tr>
<th>Category</th>
<th>This Permission...</th>
- <th>Implies This Feature Requirement</th>
+ <th>...Implies This Feature Requirement</th>
<!-- <th>Comments</th> -->
</tr>
diff --git a/docs/html/images/testing/test_framework.png b/docs/html/images/testing/test_framework.png
deleted file mode 100644
index fbc5fc2..0000000
--- a/docs/html/images/testing/test_framework.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/license.jd b/docs/html/license.jd
index 0f671e2..4f4036b 100644
--- a/docs/html/license.jd
+++ b/docs/html/license.jd
@@ -29,7 +29,9 @@
documentation (code comments) extracted from a source code module that
is licensed under GPLv2 or other license. In those cases, the license
covering the source code module will apply to the documentation
-extracted from it. </p>
+extracted from it. Source code modules that are used in the generation
+of documentation and have licenses that require attribution can be
+found in the <a href="#doclicenses">Documentation Licences section</a> below.</p>
<p>Third-party components of this site such as JavaScript libraries are included in the Android
Open Source Project under the licenses specified by their authors. For information about these
@@ -144,4 +146,102 @@
written attribution in the spirit of the messages above.
</p>
+<h2 id="doclicenses">Documentation Licenses</h2>
+<h3 id="icu">ICU License</h3>
+<p>The Android public API documentation incorporates text from the following source code libraries under the ICU License:</p>
+<ul>
+<li><a href="{@docRoot}reference/android/icu/lang/package-summary.html">android.icu.lang</a></li>
+<li><a href="{@docRoot}reference/android/icu/math/package-summary.html">android.icu.math</a></li>
+<li><a href="{@docRoot}reference/android/icu/text/package-summary.html">android.icu.text</a></li>
+<li><a href="{@docRoot}reference/android/icu/util/package-summary.html">android.icu.util</a></li>
+</ul>
+
+<div class="aside" style="overflow:scroll; height:250px;">
+<p>COPYRIGHT AND PERMISSION NOTICE</p>
+
+<p>
+Copyright (c) 1995-2015 International Business Machines Corporation and others
+</p>
+<p>
+All rights reserved.
+</p>
+<p>
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, and/or sell
+copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies
+of the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+</p>
+<p>
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL
+THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM,
+OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+USE OR PERFORMANCE OF THIS SOFTWARE.
+</p>
+<p>
+Except as contained in this notice, the name of a copyright holder shall not be
+used in advertising or otherwise to promote the sale, use or other dealings in
+this Software without prior written authorization of the copyright holder.
+</p>
+</div>
+
+<h3 id="w3c_license">W3C Software and Document Notice and License</h3>
+<p>The Android public API documentation incorporates text from the following source code libraries under the W3C Software and Document Notice and License:</p>
+<ul>
+<li><a href="{@docRoot}reference/org/w3c/dom/package-summary.html">org.w3c.dom</a></li>
+<li><a href="{@docRoot}reference/org/w3c/dom/ls/package-summary.html">org.w3c.dom.ls</a></li>
+</ul>
+
+<div class="aside" style="overflow:scroll; height:250px;">
+<p>This work is being provided by the copyright holders under the following license.</p>
+<h5>License</h5>
+<p>
+ By obtaining and/or copying this work, you (the licensee) agree that you have read, understood,
+ and will comply with the following terms and conditions.
+</p>
+<p>
+ Permission to copy, modify, and distribute this work, with or without modification, for any
+ purpose and without fee or royalty is hereby granted, provided that you include the following on
+ ALL copies of the work or portions thereof, including modifications:
+</p>
+<ul>
+<li>
+ The full text of this NOTICE in a location viewable to users of the redistributed or
+ derivative work.
+</li>
+<li>
+ Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none
+ exist, the W3C Software and Document Short Notice should be included.
+</li>
+<li>
+ Notice of any changes or modifications, through a copyright statement on the new code or document
+ such as "This software or document includes material copied from or derived from [title and URI of
+ the W3C document]. Copyright © [YEAR] W3C® (MIT, ERCIM, Keio, Beihang)."
+</li>
+</ul>
+<h5>Disclaimers</h5>
+<p>
+ THIS WORK IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
+ PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENT WILL NOT INFRINGE ANY THIRD PARTY
+ PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+</p>
+<p>
+ COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES
+ ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENT.
+</p>
+<p>
+ The name and trademarks of copyright holders may NOT be used in advertising or publicity
+ pertaining to the work without specific, written prior permission. Title to copyright in this work
+ will at all times remain with copyright holders.
+</p>
+</div>
</div>
diff --git a/docs/html/ndk/guides/audio/opensl-prog-notes.jd b/docs/html/ndk/guides/audio/opensl-prog-notes.jd
index 3263145..e70aa08 100644
--- a/docs/html/ndk/guides/audio/opensl-prog-notes.jd
+++ b/docs/html/ndk/guides/audio/opensl-prog-notes.jd
@@ -61,8 +61,8 @@
create array and can be added
later after the object is created. The Android implementation provides
a convenience feature to
-avoid this complexity; see the
- <a href="#dynamic-interfaces">Dynamic interfaces at object creation</a> section above.
+avoid this complexity, which is described in
+ <a href="{@docRoot}ndk/guides/audio/opensl-for-android.html#dynamic-interfaces">Dynamic interfaces at object creation</a>.
</p>
<p>
diff --git a/docs/html/preview/features/security-config.jd b/docs/html/preview/features/security-config.jd
index 633c0e5..2706ced 100644
--- a/docs/html/preview/features/security-config.jd
+++ b/docs/html/preview/features/security-config.jd
@@ -18,7 +18,7 @@
</ol>
</li>
<li><a href="#TrustingDebugCa">Debugging-only CAs</a></li>
- <li><a href="#UsesCleartextTraffic">Opting Out of Cleartext Traffic</a></li>
+ <li><a href="#CleartextTrafficPermitted">Opting Out of Cleartext Traffic</a></li>
<li><a href="#CertificatePinning">Pinning Certificates</a></li>
<li><a href="#ConfigInheritance">Configuration Inheritance Behavior</a></li>
<li><a href="#FileFormat">Configuration File Format</a></li>
@@ -72,9 +72,8 @@
<pre>
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
- <application ... >
- <meta-data android:name="android.security.net.config"
- android:resource="@xml/network_security_config" />
+ <application android:networkSecurityConfig="@xml/network_security_config"
+ ... >
...
</application>
</manifest>
@@ -240,7 +239,7 @@
</p>
-<h2 id="UsesCleartextTraffic">Opting Out of Cleartext Traffic</h2>
+<h2 id="CleartextTrafficPermitted">Opting Out of Cleartext Traffic</h2>
<p>
Applications intending to connect to destinations using only secure
@@ -263,7 +262,7 @@
<pre>
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
- <domain-config usesCleartextTraffic="false">
+ <domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">secure.example.com</domain>
</domain-config>
</network-security-config>
@@ -436,7 +435,7 @@
<pre class="stx">
<base-config <a href=
-"#usesCleartextTraffic">usesCleartextTraffic</a>=["true" | "false"]>
+"#CleartextTrafficPermitted">cleartextTrafficPermitted</a>=["true" | "false"]>
...
</base-config>
</pre>
@@ -463,7 +462,7 @@
</p>
<pre>
-<base-config usesCleartextTraffic="true">
+<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
@@ -471,7 +470,7 @@
</pre>
The default configuration for apps targeting API level 23 and below is:
<pre>
-<base-config usesCleartextTraffic="true">
+<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
@@ -486,7 +485,7 @@
<dl class="xml">
<dt>syntax:</dt>
<dd>
-<pre class="stx"><domain-config <a href="#usesCleartextTraffic">usesCleartextTraffic</a>=["true" | "false"]>
+<pre class="stx"><domain-config <a href="#CleartextTrafficPermitted">cleartextTrafficPermitted</a>=["true" | "false"]>
...
</domain-config></pre>
</dd>
diff --git a/docs/html/preview/setup-sdk.jd b/docs/html/preview/setup-sdk.jd
index 28fc406..3b479e2 100644
--- a/docs/html/preview/setup-sdk.jd
+++ b/docs/html/preview/setup-sdk.jd
@@ -98,7 +98,7 @@
SHA-1: 9224bd4445cd7f653c4c294d362ccb195a2101e7
</td>
</tr>
-<table>
+</table>
@@ -189,4 +189,3 @@
and <a href="{@docRoot}preview/api-overview.html">Android N APIs
and Features</a>.</li>
</ul>
-
diff --git a/docs/html/topic/instant-apps/faqs.jd b/docs/html/topic/instant-apps/faqs.jd
index 0a1f571..bf37241 100644
--- a/docs/html/topic/instant-apps/faqs.jd
+++ b/docs/html/topic/instant-apps/faqs.jd
@@ -63,7 +63,9 @@
<strong>How can developers get involved?</strong>
<br/>
Developers interested in upgrading their Android apps can visit
- <a class="external-link" href="g.co/InstantApps">g.co/InstantApps</a> to
+ <a class="external-link"
+ href="http://g.co/InstantApps">
+ g.co/InstantApps</a> to
sign up. We will be reaching out to interested
developers in the coming months.
</p>
\ No newline at end of file
diff --git a/docs/html/topic/instant-apps/index.jd b/docs/html/topic/instant-apps/index.jd
index d8de0b5..e2da9c5 100644
--- a/docs/html/topic/instant-apps/index.jd
+++ b/docs/html/topic/instant-apps/index.jd
@@ -12,17 +12,8 @@
<!-- Hero section -->
<section class="dac-expand dac-hero dac-section-light">
<div class="wrap">
- <div class="cols dac-hero-content">
-
- <div class="col-1of2 col-push-1of2 dac-hero-figure">
- <div class="dev-bytes-video">
- <iframe width="560" height="350" src=
- "https://www.youtube.com/embed/cosqlfqrpFA" frameborder="0"
- allowfullscreen=""></iframe>
- </div>
- </div>
-
- <div class="col-1of2 col-pull-1of2" style="margin-bottom:40px">
+ <div class="dac-hero-content">
+ <div style="margin-bottom:40px">
<h1>
Android Instant Apps
</h1>
@@ -47,6 +38,11 @@
<a class="landing-button green download-bundle-button" href=
"https://docs.google.com/a/google.com/forms/d/1S3MzsMVIlchLCqyNLaFbv64llxWaf90QSeYLeswco90/viewform"
target="_blank">I'M INTERESTED IN ANDROID INSTANT APPS<br></a>
+ <a class="dac-hero-cta dev-bytes"
+ href="https://www.youtube.com/watch?v=cosqlfqrpFA">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Watch a video about Instant Apps
+ </a>
</p>
</div>
@@ -56,7 +52,7 @@
<!-- Second section -->
-<div class="wrap" style="margin-top:60px">
+<div class="wrap sub-section">
<div class="cols dac-hero-content">
<div class="col-1of2 dac-hero-figure">
<img src="/images/topic/instant-apps/instant-apps-section-2.png">
@@ -64,7 +60,7 @@
<div class="col-1of2">
<div class="dac-hero-tag"></div>
- <h2 id="section-2">Run Android Apps Without Installation</h2>
+ <h2 id="section-2" class="norule">Run Android Apps Without Installation</h2>
<p class="dac-hero-description">
Android Instant Apps lets you experience beautiful and immersive
apps, with material design and smooth animations, without installing them
@@ -77,9 +73,9 @@
<!-- Third section -->
-<div class="wrap" style="margin-top:60px">
+<div class="wrap sub-section">
- <h2 id="section-3">Access Apps From Anywhere</h2>
+ <h2 id="section-3" class="norule">Access Apps From Anywhere</h2>
<p>
Get people to your flagship Android experience from links that would
@@ -126,7 +122,7 @@
<!-- Fourth section -->
-<div class="wrap" style="margin-top:60px">
+<div class="wrap sub-section">
<div class="cols dac-hero-content">
<div class="col-1of2 dac-hero-figure">
<img src="/images/topic/instant-apps/instant-apps-section-4.png">
@@ -134,9 +130,10 @@
<div class="col-1of2">
<div class="dac-hero-tag"></div>
- <h2 id="section-4">Built On Google Play Services</h2>
+ <h2 id="section-4" class="norule">Built On Google Play Services</h2>
<p class="dac-hero-description">
- Take advantage of Google Play services features — like location, identity,
+ Take advantage of Google Play services features — like location,
+ identity,
payments, and Firebase — which are built right in for a seamless user
experience.
</p>
@@ -147,17 +144,16 @@
<!-- Fifth section -->
-<div class="wrap" style="margin-top:60px">
+<div class="wrap sub-section">
<div class="cols dac-hero-content">
<div class="col-1of2 col-push-1of2 dac-hero-figure">
<img src="/images/topic/instant-apps/instant-apps-section-5.png">
</div>
<div class="col-1of2 col-pull-1of2">
<div class="dac-hero-tag"></div>
- <h2 id="section-5">Works On Most Android Devices</h2>
+ <h2 id="section-5" class="norule">Works On Most Android Devices</h2>
<p class="dac-hero-description">
-
Android Instant Apps can work on Android devices running Android 4.1+
(API Level 16) or higher with Google Play services.
</p>
@@ -168,7 +164,7 @@
<!-- Sixth section -->
-<div class="wrap" style="margin-top:60px">
+<div class="wrap sub-section">
<div class="cols dac-hero-content">
<div class="col-1of2 dac-hero-figure">
<img src="/images/topic/instant-apps/upgrade-your-app-2x.png">
@@ -176,7 +172,7 @@
<div class="col-1of2">
<div class="dac-hero-tag"></div>
- <h2 id="section-6">Upgrade Your Existing App</h2>
+ <h2 id="section-6" class="norule">Upgrade Your Existing App</h2>
<p class="dac-hero-description">
Android Instant Apps functionality is an upgrade to your existing Android
app, not a new, separate app. It's the same Android APIs, the same
@@ -192,18 +188,18 @@
<!-- Seventh section -->
-<div class="wrap" style="margin-top:60px" id="section-7">
- <h2 id="sign-up-docs" style="margin-bottom: 0px;">
+<div class="wrap sub-section" id="section-7">
+ <h2 id="sign-up-docs" class="dac-section-title norule" style="margin-bottom: 0px;">
Sign up for access to Android Instant Apps documentation
</h2>
- <p>
+ <p class="dac-section-subtitle" style="margin-top:0px">
We’ll let you know if you’re selected for early access
to Android Instant
Apps.
</p>
- <p>
+ <p class="dac-section-subtitle">
<a class="landing-button green download-bundle-button"
href="https://docs.google.com/forms/d/1S3MzsMVIlchLCqyNLaFbv64llxWaf90QSeYLeswco90/viewform"
target="_blank">
@@ -211,7 +207,7 @@
</a>
</p>
- <p style="margin-top:24px">
+ <p class="dac-section-subtitle" style="margin-top:24px">
Check out our <a href="faqs.html">frequently asked questions</a> to find out
more about Android Instant Apps.
</p>
@@ -230,28 +226,14 @@
background: #B0BEC5;
}
- /* Styling and layout for video. */
- .dev-bytes-video {
- margin-top: 30px;
- position: relative;
- padding-bottom: 56.25%; /* 16:9 */
- padding-top: 30px;
- height: 0;
- }
-
- .dev-bytes-video iframe,
- .dev-bytes-video object,
- .dev-bytes-video embed {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- }
-
/* Increase top margin for sections */
- .wrap {
- margin-top: 1.5em;
+ .sub-section {
+ margin-top: 2em;
+ }
+
+ a.dev-bytes {
+ padding-top: 1em;
+ padding-left: 1em;
}
#section-3, #sign-up-docs {
@@ -259,11 +241,6 @@
border-top: 0px;
}
- /* Align the seventh section in the center. */
- #section-7 {
- text-align: center;
- }
-
/* GIF section styling */
.figure-caption {
text-align: center;
diff --git a/docs/html/training/basics/firstapp/building-ui.jd b/docs/html/training/basics/firstapp/building-ui.jd
index 402396e..275500c 100644
--- a/docs/html/training/basics/firstapp/building-ui.jd
+++ b/docs/html/training/basics/firstapp/building-ui.jd
@@ -396,20 +396,13 @@
<h2>Run Your App</h2>
<p>This layout is applied by the default {@link android.app.Activity} class
-that the SDK tools generated when you created the project. Run the app to see the
-results:</p>
+that the SDK tools generated when you created the project.</p>
-<ul>
- <li>In Android Studio, from the toolbar, click <strong>Run</strong>
+<p>To run the app and see the results,
+ click <strong>Run 'app'</strong>
<img src="{@docRoot}images/tools/as-run.png"
- style="vertical-align:baseline;margin:0; max-height:1em" />.</li>
- <li>Or from a command line, change directories to the root of your Android project and
-execute:
-<pre class="no-pretty-print">
-$ ant debug
-adb install -r app/build/outputs/apk/app-debug.apk
-</pre></li>
-</ul>
+ style="vertical-align:baseline;margin:0; max-height:1em" /> in the
+ toolbar.</p>
<p>Continue to the <a href="starting-activity.html">next
lesson</a> to learn how to respond to button presses, read content
diff --git a/docs/html/training/basics/firstapp/running-app.jd b/docs/html/training/basics/firstapp/running-app.jd
index 99b38bf..21fb64d 100755
--- a/docs/html/training/basics/firstapp/running-app.jd
+++ b/docs/html/training/basics/firstapp/running-app.jd
@@ -76,46 +76,6 @@
<p>Android Studio installs the app on your connected device and starts it.</p>
-<h3>Run the app from a command line</h3>
-
-<p>Open a command-line and navigate to the root of your project directory.
- Use Gradle to build your project in debug mode, invoke the <code>assembleDebug</code> build task
- using the Gradle wrapper script (<code>gradlew assembleRelease</code>).
-
- <p>This creates your debug <code>.apk</code> file inside the module <code>build/</code>
- directory, named <code>app-debug.apk</code>. </p>
-
- <p>On Windows platforms, type this command:</p>
-
-<pre>
-> gradlew.bat assembleDebug
-</pre>
-
-<p>On Mac OS and Linux platforms, type these commands:</p>
-
-<pre>
-$ chmod +x gradlew
-$ ./gradlew assembleDebug
-</pre>
-
- <p>After you build the project, the output APK for the app module is located in
- <code>app/build/outputs/apk/</code>
-
- <p class="note"><strong>Note:</strong> The first command (<code>chmod</code>) adds the execution
- permission to the Gradle wrapper script and is only necessary the first time you build this
- project from the command line.</p>
-
- <p>Make sure the Android SDK <code>platform-tools/</code> directory is included in your
- <code>PATH</code> environment variable, then execute:
- <pre class="no-pretty-print">$ adb install app/build/outputs/apk/app-debug.apk</pre><p>
- <p>On your device, locate <em>MyFirstApp</em> and open it.</p>
-
-<p>That's how you build and run your Android app on a device!
- To start developing, continue to the <a href="building-ui.html">next
-lesson</a>.</p>
-
-
-
<h2 id="Emulator">Run on the Emulator</h2>
<p>Whether you're using Android Studio or the command line, to run your app on the emulator you need
@@ -168,23 +128,8 @@
When you do, <em>My First App</em> appears on the emulator screen.</p>
-<h3>Run your app from the command line</h3>
- <ol>
- <li>Build the project from the command line. The output APK for the app module is located in
- <code>app/build/outputs/apk/</code>.</li>
- <li>Make sure the Android SDK <code>platform-tools/</code> directory is included in your
- <code>PATH</code> environment variable.</li>
- <li>Execute this command:
- <p>
- <pre class="no-pretty-print">$ adb install app/build/outputs/apk/apk-debug.apk</pre>
- </p>
- </li>
- <li>On the emulator, locate <em>MyFirstApp</em> and open it.</li>
- </ol>
-
-
- <p>That's how you build and run your Android app on the emulator!
- To start developing, continue to the <a href="building-ui.html">next
- lesson</a>.</p>
+<p>That's how you build and run your Android app on the emulator!
+To start developing, continue to the <a href="building-ui.html">next
+lesson</a>.</p>
diff --git a/docs/html/training/volley/request.jd b/docs/html/training/volley/request.jd
index a2b2ecd..97efc17 100644
--- a/docs/html/training/volley/request.jd
+++ b/docs/html/training/volley/request.jd
@@ -38,7 +38,7 @@
<p>If your expected response is one of these types, you probably won't have to implement a
custom request. This lesson describes how to use these standard request types. For
-information on how to implement your own custom request, see <a href="requests-custom.html">
+information on how to implement your own custom request, see <a href="request-custom.html">
Implementing a Custom Request</a>.</p>
diff --git a/docs/html/wear/preview/downloads.jd b/docs/html/wear/preview/downloads.jd
index b119d57..8689504 100644
--- a/docs/html/wear/preview/downloads.jd
+++ b/docs/html/wear/preview/downloads.jd
@@ -418,13 +418,15 @@
devices, <code>fastboot oem unlock</code>
</li>
- <li>Navigate to the directory where you unzipped the system image in Step
- 1.
+ <li>On the watch, select the <strong>Unlock</strong> option.
</li>
- <li>Execute the <code>flash-all</code> script by typing
+ <li>Navigate to the directory where you unzipped the system image in Step
+ 1. At the top level of that directory,
+ execute the <code>flash-all</code> script by typing
<code>flash-all.sh</code> or, in the case of Windows,
- <code>flash-all.bat</code>.
+ <code>flash-all.bat</code>. The following may need to
+ precede the command: <code>./</code>
</li>
</ol>
@@ -434,40 +436,10 @@
</h4>
<p>
- After the <code>flash-all</code> script finishes, your watch reboots
- and soon will be ready for testing with the preview image.
- </p>
-
- <ol>
- <li>Attach the watch charger to the watch and plug the USB cord
- into your computer, if it is not already plugged in.
- </li>
-
- <li>Use the following <a href="{@docRoot}tools/help/adb.html">adb
- command</a> to confirm that the watch is available:
- <code>adb devices</code>
- </li>
-
- <li>Use the following adb command to start the device in fastboot mode:
- <code>adb reboot bootloader</code>
- </li>
-
- <li>Use the following command to
- lock the device's bootloader: <code>fastboot flashing lock</code> or, for some
- devices, <code>fastboot oem lock</code>
- </li>
-
- <li>On the watch, continue the boot by touching <strong>'0'</strong>.
- </li>
-
- </ol>
-
-
- <p>
- Pair the watch with a
- phone or tablet. The preview now is available for testing on the watch.
- Before installing an app, enable the Developer Options menu, and ADB
- debugging, on the watch as follows:
+ After the <code>flash-all</code> script finishes, your watch reboots.
+ Pair the watch with a phone or tablet. The preview now is available
+ for testing on the watch. Before installing an app, perform the
+ following steps on the watch to re-secure the watch's bootloader:
</p>
<ol>
@@ -490,6 +462,19 @@
<li>Connect the watch to your computer and tap <strong>Always allow from
this computer</strong>.
</li>
+
+ <li>Use the following adb command to start the device in fastboot mode:
+ <code>adb reboot bootloader</code>
+ </li>
+
+ <li>Use the following command to
+ lock the device's bootloader: <code>fastboot flashing lock</code> or, for some
+ devices, <code>fastboot oem lock</code>
+ </li>
+
+ <li>On the watch, continue the boot by choosing
+ <strong>Start</strong> and touching <strong>'0'</strong>.
+ </li>
</ol>
<p>
@@ -502,8 +487,8 @@
<li>Open your app in Android Studio.
</li>
- <li>Select <strong>wear</strong> from the Run/Debug configuration
- drop-down menu.
+ <li>Select your Wear app module name from the Run/Debug configuration
+ drop-down menu (typically <strong>wear</strong>).
</li>
<li>Click the Play button.
@@ -514,8 +499,7 @@
</ol>
<p>
- After your app is installed on the watch, you are prompted to start the
- app on the watch.
+ After your app is installed on the watch, the app should run.
</p>
<p>
@@ -567,10 +551,12 @@
<li>Click <strong>Create Virtual Device</strong>.
</li>
- <li>In the <strong>Category</strong> pane, select Wear, choose a hardware profile,
- and click <strong>Next</strong>. The Android Wear 2.0 Developer Preview
+ <li>In the <strong>Category</strong> pane, select Wear and
+ choose a hardware profile.
+ The Android Wear 2.0 Developer Preview
is only optimized for round devices currently, so we recommend not
using the square or chin profiles for now.
+ Click <strong>Next</strong>.
</li>
<li>Select an <strong>N</strong> image to download. The images may be on
@@ -588,7 +574,8 @@
</ol>
<p>
- You can now test an application in the <a href=
+ You can now test an application with a virtual preview device
+ in the <a href=
"{@docRoot}tools/devices/emulator.html">Android Emulator</a>. For more
information about using virtual devices, see <a href=
"{@docRoot}tools/devices/managing-avds.html">Managing AVDs with the AVD
diff --git a/docs/html/wear/preview/features/ui-nav-actions.jd b/docs/html/wear/preview/features/ui-nav-actions.jd
index 800fc8e..1ba275f 100644
--- a/docs/html/wear/preview/features/ui-nav-actions.jd
+++ b/docs/html/wear/preview/features/ui-nav-actions.jd
@@ -19,10 +19,10 @@
<h2>You should also read</h2>
<ul>
- <li><a href="http://www.google.com/design/wear-spec/components/navigation-drawer.html">
+ <li><a href="http://www.google.com/design/spec-wear/components/navigation-drawer.html">
Navigation Drawer Design</a> </li>
<li>
- <a href="http://www.google.com/design/wear-spec/components/action-drawer.html">
+ <a href="http://www.google.com/design/spec-wear/components/action-drawer.html">
Action Drawer Design</a>
</ul>
@@ -76,6 +76,7 @@
<android.support.wearable.view.drawer.WearableDrawerLayout
android:id="@+id/drawer_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:deviceIds="wear">
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 8971004..c6977746 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -500,34 +500,44 @@
* @param d The drawable to initialize.
*/
private void initializeDrawableForDisplay(Drawable d) {
- if (mDrawableContainerState.mEnterFadeDuration <= 0 && mHasAlpha) {
- d.setAlpha(mAlpha);
- }
+ // Temporary fix for suspending callbacks during initialization. We
+ // don't want any of these setters causing an invalidate() since that
+ // may call back into DrawableContainer.
+ final Callback cb = d.getCallback();
+ d.setCallback(null);
- if (mDrawableContainerState.mHasColorFilter) {
- // Color filter always overrides tint.
- d.setColorFilter(mDrawableContainerState.mColorFilter);
- } else {
- if (mDrawableContainerState.mHasTintList) {
- d.setTintList(mDrawableContainerState.mTintList);
+ try {
+ if (mDrawableContainerState.mEnterFadeDuration <= 0 && mHasAlpha) {
+ d.setAlpha(mAlpha);
}
- if (mDrawableContainerState.mHasTintMode) {
- d.setTintMode(mDrawableContainerState.mTintMode);
+
+ if (mDrawableContainerState.mHasColorFilter) {
+ // Color filter always overrides tint.
+ d.setColorFilter(mDrawableContainerState.mColorFilter);
+ } else {
+ if (mDrawableContainerState.mHasTintList) {
+ d.setTintList(mDrawableContainerState.mTintList);
+ }
+ if (mDrawableContainerState.mHasTintMode) {
+ d.setTintMode(mDrawableContainerState.mTintMode);
+ }
}
- }
- d.setVisible(isVisible(), true);
- d.setDither(mDrawableContainerState.mDither);
- d.setState(getState());
- d.setLevel(getLevel());
- d.setBounds(getBounds());
- d.setLayoutDirection(getLayoutDirection());
- d.setAutoMirrored(mDrawableContainerState.mAutoMirrored);
+ d.setVisible(isVisible(), true);
+ d.setDither(mDrawableContainerState.mDither);
+ d.setState(getState());
+ d.setLevel(getLevel());
+ d.setBounds(getBounds());
+ d.setLayoutDirection(getLayoutDirection());
+ d.setAutoMirrored(mDrawableContainerState.mAutoMirrored);
- final Rect hotspotBounds = mHotspotBounds;
- if (hotspotBounds != null) {
- d.setHotspotBounds(hotspotBounds.left, hotspotBounds.top,
- hotspotBounds.right, hotspotBounds.bottom);
+ final Rect hotspotBounds = mHotspotBounds;
+ if (hotspotBounds != null) {
+ d.setHotspotBounds(hotspotBounds.left, hotspotBounds.top,
+ hotspotBounds.right, hotspotBounds.bottom);
+ }
+ } finally {
+ d.setCallback(cb);
}
}
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index c67b008..1864206 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -104,6 +104,9 @@
private Rect mHotspotBounds;
private boolean mMutated;
+ private boolean mSuspendChildInvalidation;
+ private boolean mChildRequestedInvalidation;
+
/**
* Creates a new layer drawable with the list of specified layers.
*
@@ -944,9 +947,37 @@
return mLayerState.mPaddingMode;
}
+ /**
+ * Temporarily suspends child invalidation.
+ *
+ * @see #resumeChildInvalidation()
+ */
+ private void suspendChildInvalidation() {
+ mSuspendChildInvalidation = true;
+ }
+
+ /**
+ * Resumes child invalidation after suspension, immediately performing an
+ * invalidation if one was requested by a child during suspension.
+ *
+ * @see #suspendChildInvalidation()
+ */
+ private void resumeChildInvalidation() {
+ mSuspendChildInvalidation = false;
+
+ if (mChildRequestedInvalidation) {
+ mChildRequestedInvalidation = false;
+ invalidateSelf();
+ }
+ }
+
@Override
public void invalidateDrawable(@NonNull Drawable who) {
- invalidateSelf();
+ if (mSuspendChildInvalidation) {
+ mChildRequestedInvalidation = true;
+ } else {
+ invalidateSelf();
+ }
}
@Override
@@ -1482,6 +1513,15 @@
}
private void updateLayerBounds(Rect bounds) {
+ try {
+ suspendChildInvalidation();
+ updateLayerBoundsInternal(bounds);
+ } finally {
+ resumeChildInvalidation();
+ }
+ }
+
+ private void updateLayerBoundsInternal(Rect bounds) {
int paddingL = 0;
int paddingT = 0;
int paddingR = 0;
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 746e99a..cb8e55f 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -878,11 +878,49 @@
restoreForLayer();
+ // saveLayer will clip & translate the draw contents, so we need
+ // to translate the drawLayer by how much the contents was translated
+ // TODO: Unify this with beginLayerOp so we don't have to calculate this
+ // twice
+ uint32_t layerWidth = (uint32_t) beginLayerOp.unmappedBounds.getWidth();
+ uint32_t layerHeight = (uint32_t) beginLayerOp.unmappedBounds.getHeight();
+
+ auto previous = mCanvasState.currentSnapshot();
+ Vector3 lightCenter = previous->getRelativeLightCenter();
+
+ // Combine all transforms used to present saveLayer content:
+ // parent content transform * canvas transform * bounds offset
+ Matrix4 contentTransform(*(previous->transform));
+ contentTransform.multiply(beginLayerOp.localMatrix);
+ contentTransform.translate(beginLayerOp.unmappedBounds.left,
+ beginLayerOp.unmappedBounds.top);
+
+ Matrix4 inverseContentTransform;
+ inverseContentTransform.loadInverse(contentTransform);
+
+ // map the light center into layer-relative space
+ inverseContentTransform.mapPoint3d(lightCenter);
+
+ // Clip bounds of temporary layer to parent's clip rect, so:
+ Rect saveLayerBounds(layerWidth, layerHeight);
+ // 1) transform Rect(width, height) into parent's space
+ // note: left/top offsets put in contentTransform above
+ contentTransform.mapRect(saveLayerBounds);
+ // 2) intersect with parent's clip
+ saveLayerBounds.doIntersect(previous->getRenderTargetClip());
+ // 3) and transform back
+ inverseContentTransform.mapRect(saveLayerBounds);
+ saveLayerBounds.doIntersect(Rect(layerWidth, layerHeight));
+ saveLayerBounds.roundOut();
+
+ Matrix4 localMatrix(beginLayerOp.localMatrix);
+ localMatrix.translate(saveLayerBounds.left, saveLayerBounds.top);
+
// record the draw operation into the previous layer's list of draw commands
// uses state from the associated beginLayerOp, since it has all the state needed for drawing
LayerOp* drawLayerOp = mAllocator.create_trivial<LayerOp>(
beginLayerOp.unmappedBounds,
- beginLayerOp.localMatrix,
+ localMatrix,
beginLayerOp.localClip,
beginLayerOp.paint,
&(mLayerBuilders[finishedLayerIndex]->offscreenBuffer));
diff --git a/libs/hwui/OpDumper.cpp b/libs/hwui/OpDumper.cpp
index cab93e8..ec9ffde 100644
--- a/libs/hwui/OpDumper.cpp
+++ b/libs/hwui/OpDumper.cpp
@@ -45,5 +45,9 @@
}
}
+const char* OpDumper::opName(const RecordedOp& op) {
+ return sOpNameLut[op.opId];
+}
+
} // namespace uirenderer
} // namespace android
diff --git a/libs/hwui/OpDumper.h b/libs/hwui/OpDumper.h
index c99b517..a82289c 100644
--- a/libs/hwui/OpDumper.h
+++ b/libs/hwui/OpDumper.h
@@ -26,6 +26,7 @@
class OpDumper {
public:
static void dump(const RecordedOp& op, std::ostream& output, int level = 0);
+ static const char* opName(const RecordedOp& op);
};
}; // namespace uirenderer
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 0f16b15..af1fbd8 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -2025,6 +2025,7 @@
uint32_t layerHeight = 0;
Rect rectClippedBounds;
Matrix4 rectMatrix;
+ Matrix4 drawLayerMatrix;
};
/**
* Constructs a view to hit the temporary layer alpha property implementation:
@@ -2060,6 +2061,7 @@
}
void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
EXPECT_EQ(3, mIndex++);
+ mOutData->drawLayerMatrix = state.computedState.transform;
}
void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
EXPECT_EQ(4, mIndex++);
@@ -2108,6 +2110,9 @@
expected.loadTranslate(0, -2000, 0);
EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix)
<< "expect content to be translated as part of being clipped";
+ expected.loadTranslate(10, 0, 0);
+ EXPECT_MATRIX_APPROX_EQ(expected, observedData.drawLayerMatrix)
+ << "expect drawLayer to be translated as part of being clipped";
}
RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) {
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 61f78cc..27193b7 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -90,7 +90,6 @@
mLocked.lastFrameUpdatedTime = 0;
mLocked.buttonState = 0;
- mLocked.iconDetached = false;
mPolicy->loadPointerIcon(&mLocked.pointerIcon);
@@ -185,10 +184,6 @@
}
void PointerController::setPositionLocked(float x, float y) {
- if (mLocked.iconDetached) {
- return;
- }
-
float minX, minY, maxX, maxY;
if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
if (x <= minX) {
@@ -222,10 +217,6 @@
// Remove the inactivity timeout, since we are fading now.
removeInactivityTimeoutLocked();
- if (mLocked.iconDetached) {
- return;
- }
-
// Start fading.
if (transition == TRANSITION_IMMEDIATE) {
mLocked.pointerFadeDirection = 0;
@@ -243,10 +234,6 @@
// Always reset the inactivity timer.
resetInactivityTimeoutLocked();
- if (mLocked.iconDetached) {
- return;
- }
-
// Start unfading.
if (transition == TRANSITION_IMMEDIATE) {
mLocked.pointerFadeDirection = 0;
@@ -362,22 +349,6 @@
updatePointerLocked();
}
-void PointerController::detachPointerIcon(bool detached) {
- AutoMutex _l(mLock);
-
- if (mLocked.iconDetached == detached) {
- return;
- }
-
- mLocked.iconDetached = detached;
- if (detached) {
- mLocked.pointerFadeDirection = -1;
- } else {
- mLocked.pointerFadeDirection = 1;
- }
- startAnimationLocked();
-}
-
void PointerController::setDisplayViewport(int32_t width, int32_t height, int32_t orientation) {
AutoMutex _l(mLock);
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index b47139a..99292d7 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -111,10 +111,6 @@
void setInactivityTimeout(InactivityTimeout inactivityTimeout);
void reloadPointerResources();
- /* Detach or attach the pointer icon status. When detached, the pointer icon disappears
- * and the icon location does not change at all. */
- void detachPointerIcon(bool detached);
-
private:
static const size_t MAX_RECYCLED_SPRITES = 12;
static const size_t MAX_SPOTS = 12;
@@ -184,8 +180,6 @@
int32_t buttonState;
- bool iconDetached;
-
Vector<Spot*> spots;
Vector<sp<Sprite> > recycledSprites;
} mLocked;
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index 5561b22..b601cde 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -34,6 +34,7 @@
private static final int NUM_SATELLITES = 255;
private static final int GLONASS_SVID_OFFSET = 64;
private static final int BEIDOU_SVID_OFFSET = 200;
+ private static final int SBAS_SVID_OFFSET = -87;
/* These package private values are modified by the LocationManager class */
private int mTimeToFirstFix;
@@ -166,9 +167,10 @@
prn += GLONASS_SVID_OFFSET;
} else if (constellationType == GnssStatus.CONSTELLATION_BEIDOU) {
prn += BEIDOU_SVID_OFFSET;
+ } else if (constellationType == GnssStatus.CONSTELLATION_SBAS) {
+ prn += SBAS_SVID_OFFSET;
} else if ((constellationType != GnssStatus.CONSTELLATION_GPS) &&
- (constellationType != GnssStatus.CONSTELLATION_QZSS) &&
- (constellationType != GnssStatus.CONSTELLATION_SBAS)) {
+ (constellationType != GnssStatus.CONSTELLATION_QZSS)) {
continue;
}
if (prn > 0 && prn <= NUM_SATELLITES) {
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index a3bbdfc..5286f8f 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -225,9 +225,20 @@
public final static int FLAG_BYPASS_MUTE = 0x1 << 7;
/**
- * Flag requesting a low latency path.
+ * Flag requesting a low latency path when creating an AudioTrack.
* When using this flag, the sample rate must match the native sample rate
* of the device. Effects processing is also unavailable.
+ *
+ * Note that if this flag is used without specifying a bufferSizeInBytes then the
+ * AudioTrack's actual buffer size may be too small. It is recommended that a fairly
+ * large buffer should be specified when the AudioTrack is created.
+ * Then the actual size can be reduced by calling
+ * {@link AudioTrack#setBufferSizeInFrames(int)}. The buffer size can be optimized
+ * by lowering it after each write() call until the audio glitches, which is detected by calling
+ * {@link AudioTrack#getUnderrunCount()}. Then the buffer size can be increased
+ * until there are no glitches.
+ * This tuning step should be done while playing silence.
+ * This technique provides a compromise between latency and glitch rate.
*/
public final static int FLAG_LOW_LATENCY = 0x1 << 8;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 7178313..4bdc70e 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2747,13 +2747,6 @@
*/
public static abstract class AudioRecordingCallback {
/**
- * This method is deprecated, override {@link #onRecordingConfigChanged(List)} instead.
- * @param configs
- * @removed
- */
- @Deprecated
- public void onRecordingConfigChanged(AudioRecordingConfiguration[] configs) {}
- /**
* Called whenever the device recording configuration has changed.
* @param configs list containing the results of
* {@link AudioManager#getActiveRecordingConfigurations()}.
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 87c6d88..349d67e 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -567,6 +567,34 @@
return false;
}
}
+
+ Integer profile = (Integer)map.get(MediaFormat.KEY_PROFILE);
+ Integer level = (Integer)map.get(MediaFormat.KEY_LEVEL);
+
+ if (profile != null) {
+ if (!supportsProfileLevel(profile, level)) {
+ return false;
+ }
+
+ // If we recognize this profile, check that this format is supported by the
+ // highest level supported by the codec for that profile. (Ignore specified
+ // level beyond the above profile/level check as level is only used as a
+ // guidance. E.g. AVC Level 1 CIF format is supported if codec supports level 1.1
+ // even though max size for Level 1 is QCIF. However, MPEG2 Simple Profile
+ // 1080p format is not supported even if codec supports Main Profile Level High,
+ // as Simple Profile does not support 1080p.
+ CodecCapabilities levelCaps = null;
+ int maxLevel = 0;
+ for (CodecProfileLevel pl : profileLevels) {
+ if (pl.profile == profile && pl.level > maxLevel) {
+ maxLevel = pl.level;
+ }
+ }
+ levelCaps = createFromProfileLevel(mMime, profile, maxLevel);
+ if (levelCaps != null && !levelCaps.isFormatSupported(format)) {
+ return false;
+ }
+ }
if (mAudioCaps != null && !mAudioCaps.supportsFormat(format)) {
return false;
}
@@ -579,6 +607,57 @@
return true;
}
+ private static boolean supportsBitrate(
+ Range<Integer> bitrateRange, MediaFormat format) {
+ Map<String, Object> map = format.getMap();
+
+ // consider max bitrate over average bitrate for support
+ Integer maxBitrate = (Integer)map.get(MediaFormat.KEY_MAX_BIT_RATE);
+ Integer bitrate = (Integer)map.get(MediaFormat.KEY_BIT_RATE);
+ if (bitrate == null) {
+ bitrate = maxBitrate;
+ } else if (maxBitrate != null) {
+ bitrate = Math.max(bitrate, maxBitrate);
+ }
+
+ if (bitrate != null && bitrate > 0) {
+ return bitrateRange.contains(bitrate);
+ }
+
+ return true;
+ }
+
+ private boolean supportsProfileLevel(int profile, Integer level) {
+ for (CodecProfileLevel pl: profileLevels) {
+ if (pl.profile != profile) {
+ continue;
+ }
+
+ // AAC does not use levels
+ if (level == null || mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) {
+ return true;
+ }
+
+ // H.263 levels are not completely ordered:
+ // Level45 support only implies Level10 support
+ if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)) {
+ if (pl.level != level && pl.level == CodecProfileLevel.H263Level45
+ && level > CodecProfileLevel.H263Level10) {
+ continue;
+ }
+ }
+ if (pl.level >= level) {
+ // if we recognize the listed profile/level, we must also recognize the
+ // profile/level arguments.
+ if (createFromProfileLevel(mMime, profile, pl.level) != null) {
+ return createFromProfileLevel(mMime, profile, level) != null;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
// errors while reading profile levels - accessed from sister capabilities
int mError;
@@ -1004,10 +1083,15 @@
Map<String, Object> map = format.getMap();
Integer sampleRate = (Integer)map.get(MediaFormat.KEY_SAMPLE_RATE);
Integer channels = (Integer)map.get(MediaFormat.KEY_CHANNEL_COUNT);
+
if (!supports(sampleRate, channels)) {
return false;
}
+ if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) {
+ return false;
+ }
+
// nothing to do for:
// KEY_CHANNEL_MASK: codecs don't get this
// KEY_IS_ADTS: required feature for all AAC decoders
@@ -1310,8 +1394,7 @@
return supports(width, height, null);
}
- private boolean supports(
- Integer width, Integer height, Number rate) {
+ private boolean supports(Integer width, Integer height, Number rate) {
boolean ok = true;
if (ok && width != null) {
@@ -1353,9 +1436,16 @@
Integer height = (Integer)map.get(MediaFormat.KEY_HEIGHT);
Number rate = (Number)map.get(MediaFormat.KEY_FRAME_RATE);
- // we ignore color-format for now as it is not reliably reported by codec
+ if (!supports(width, height, rate)) {
+ return false;
+ }
- return supports(width, height, rate);
+ if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) {
+ return false;
+ }
+
+ // we ignore color-format for now as it is not reliably reported by codec
+ return true;
}
/* no public constructor */
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 93c595f..33e3957 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -185,12 +185,20 @@
public static final String KEY_MAX_INPUT_SIZE = "max-input-size";
/**
- * A key describing the bitrate in bits/sec.
+ * A key describing the average bitrate in bits/sec.
* The associated value is an integer
*/
public static final String KEY_BIT_RATE = "bitrate";
/**
+ * A key describing the max bitrate in bits/sec.
+ * This is usually over a one-second sliding window (e.g. over any window of one second).
+ * The associated value is an integer
+ * @hide
+ */
+ public static final String KEY_MAX_BIT_RATE = "max-bitrate";
+
+ /**
* A key describing the color format of the content in a video format.
* Constants are declared in {@link android.media.MediaCodecInfo.CodecCapabilities}.
*/
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java
index e718742..423c3b0 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java
@@ -38,6 +38,7 @@
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.media.ImageReader;
+import android.graphics.SurfaceTexture;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
@@ -67,6 +68,7 @@
import static com.android.mediaframeworktest.helpers.CameraTestUtils.getSupportedPreviewSizes;
import static com.android.mediaframeworktest.helpers.CameraTestUtils.getSupportedStillSizes;
import static com.android.mediaframeworktest.helpers.CameraTestUtils.getSupportedVideoSizes;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.getSortedSizesForFormat;
import static com.android.mediaframeworktest.helpers.CameraTestUtils.makeImageReader;
/**
@@ -122,6 +124,8 @@
protected List<Size> mOrderedPreviewSizes; // In descending order.
protected List<Size> mOrderedVideoSizes; // In descending order.
protected List<Size> mOrderedStillSizes; // In descending order.
+ protected List<Size> mOrderedRAW10Sizes; // In descending order.
+ protected List<Size> mOrderedYUV420888Sizes; // In descending order.
protected HashMap<Size, Long> mMinPreviewFrameDurationMap;
protected WindowManager mWindowManager;
@@ -589,6 +593,7 @@
mReaderSurface = null;
}
+
/**
* Open a camera device and get the StaticMetadata for a given camera id.
*
@@ -603,8 +608,13 @@
if (mStaticInfo.isColorOutputSupported()) {
mOrderedPreviewSizes = getSupportedPreviewSizes(cameraId, mCameraManager,
getPreviewSizeBound(mWindowManager, PREVIEW_SIZE_BOUND));
- mOrderedVideoSizes = getSupportedVideoSizes(cameraId, mCameraManager, PREVIEW_SIZE_BOUND);
+ mOrderedVideoSizes = getSupportedVideoSizes(
+ cameraId, mCameraManager, PREVIEW_SIZE_BOUND);
mOrderedStillSizes = getSupportedStillSizes(cameraId, mCameraManager, null);
+ mOrderedRAW10Sizes = getSortedSizesForFormat(
+ cameraId, mCameraManager, ImageFormat.RAW10, null);
+ mOrderedYUV420888Sizes = getSortedSizesForFormat(
+ cameraId, mCameraManager, ImageFormat.YUV_420_888, null);
// Use ImageFormat.YUV_420_888 for now. TODO: need figure out what's format for preview
// in public API side.
mMinPreviewFrameDurationMap =
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2SwitchPreviewTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2SwitchPreviewTest.java
new file mode 100644
index 0000000..11327ca
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2SwitchPreviewTest.java
@@ -0,0 +1,578 @@
+/*
+ * Copyright (C) 2016 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.mediaframeworktest.stress;
+
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
+import com.android.mediaframeworktest.Camera2SurfaceViewTestCase;
+import com.android.mediaframeworktest.helpers.Camera2Focuser;
+import com.android.mediaframeworktest.helpers.CameraTestUtils;
+import com.android.mediaframeworktest.helpers.CameraTestUtils.SimpleCaptureCallback;
+
+import android.graphics.ImageFormat;
+import android.graphics.Point;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
+import android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.DngCreator;
+import android.hardware.camera2.params.MeteringRectangle;
+import android.media.Image;
+import android.media.ImageReader;
+import android.media.CamcorderProfile;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.media.MediaRecorder;
+import android.os.ConditionVariable;
+import android.os.Environment;
+import android.util.Log;
+import android.util.Pair;
+import android.util.Rational;
+import android.util.Size;
+import android.view.Surface;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.util.Range;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.io.File;
+import java.util.Arrays;
+import java.util.HashMap;
+
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.CAPTURE_IMAGE_TIMEOUT_MS;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.MAX_READER_IMAGES;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.SimpleImageReaderListener;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.basicValidateJpegImage;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.configureCameraSession;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.dumpFile;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.getDataFromImage;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.getValueNotNull;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.makeImageReader;
+import static com.android.ex.camera2.blocking.BlockingSessionCallback.SESSION_CLOSED;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.CAPTURE_IMAGE_TIMEOUT_MS;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.SESSION_CLOSE_TIMEOUT_MS;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.SIZE_BOUND_1080P;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.SIZE_BOUND_2160P;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.getSupportedVideoSizes;
+
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+import com.android.mediaframeworktest.Camera2SurfaceViewTestCase;
+import com.android.mediaframeworktest.helpers.CameraTestUtils;
+
+import junit.framework.AssertionFailedError;
+
+/**
+ * <p>Tests Back/Front camera switching and Camera/Video modes witching.</p>
+ *
+ * adb shell am instrument \
+ * -e class com.android.mediaframeworktest.stress.Camera2SwitchPreviewTest \
+ * -e iterations 200 \
+ * -e waitIntervalMs 1000 \
+ * -e resultToFile false \
+ * -r -w com.android.mediaframeworktest/.Camera2InstrumentationTestRunner
+ */
+public class Camera2SwitchPreviewTest extends Camera2SurfaceViewTestCase {
+ private static final String TAG = "SwitchPreviewTest";
+ private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ // 60 second to accommodate the possible long exposure time.
+ private static final int MAX_REGIONS_AE_INDEX = 0;
+ private static final int MAX_REGIONS_AWB_INDEX = 1;
+ private static final int MAX_REGIONS_AF_INDEX = 2;
+ private static final int WAIT_FOR_FOCUS_DONE_TIMEOUT_MS = 6000;
+ private static final double AE_COMPENSATION_ERROR_TOLERANCE = 0.2;
+ // 5 percent error margin for resulting metering regions
+ private static final float METERING_REGION_ERROR_PERCENT_DELTA = 0.05f;
+ private final String VIDEO_FILE_PATH = Environment.getExternalStorageDirectory().getPath();
+
+ private static final boolean DEBUG_DUMP = Log.isLoggable(TAG, Log.DEBUG);
+ private static final int RECORDING_DURATION_MS = 3000;
+ private static final float DURATION_MARGIN = 0.2f;
+ private static final double FRAME_DURATION_ERROR_TOLERANCE_MS = 3.0;
+ private static final int BIT_RATE_1080P = 16000000;
+ private static final int BIT_RATE_MIN = 64000;
+ private static final int BIT_RATE_MAX = 40000000;
+ private static final int VIDEO_FRAME_RATE = 30;
+ private static final int[] mCamcorderProfileList = {
+ CamcorderProfile.QUALITY_HIGH,
+ CamcorderProfile.QUALITY_2160P,
+ CamcorderProfile.QUALITY_1080P,
+ CamcorderProfile.QUALITY_720P,
+ CamcorderProfile.QUALITY_480P,
+ CamcorderProfile.QUALITY_CIF,
+ CamcorderProfile.QUALITY_QCIF,
+ CamcorderProfile.QUALITY_QVGA,
+ CamcorderProfile.QUALITY_LOW,
+ };
+ private static final int MAX_VIDEO_SNAPSHOT_IMAGES = 5;
+ private static final int BURST_VIDEO_SNAPSHOT_NUM = 3;
+ private static final int SLOWMO_SLOW_FACTOR = 4;
+ private static final int MAX_NUM_FRAME_DROP_INTERVAL_ALLOWED = 4;
+ private List<Size> mSupportedVideoSizes;
+ private Surface mRecordingSurface;
+ private Surface mPersistentSurface;
+ private MediaRecorder mMediaRecorder;
+ private String mOutMediaFileName;
+ private int mVideoFrameRate;
+ private Size mVideoSize;
+ private long mRecordingStartTime;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test normal still preview switch.
+ * <p>
+ * Preview jpeg output streams are configured. Max still capture
+ * size is used for jpeg capture.
+ * </p>
+ */
+ public void testPreviewSwitchBackFrontCamera() throws Exception {
+ List<String> mCameraColorOutputIds = cameraColorOutputCheck();
+ // Test iteration starts...
+ Log.i(TAG, "Testing preview switch back/front camera in still capture mode");
+ for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+ for (String id : mCameraColorOutputIds) {
+ try {
+ openDevice(id);
+ // Preview for basic still capture:
+ Log.v(TAG, String.format("Preview pictures: %d/%d", iteration + 1,
+ getIterationCount()));
+ stillCapturePreviewPreparer(id);
+ getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
+ } finally {
+ closeDevice();
+ closeImageReader();
+ }
+ }
+ }
+ }
+
+ /**
+ * <p>
+ * Test basic video preview switch.
+ * </p>
+ * <p>
+ * This test covers the typical basic use case of video preview switch.
+ * MediaRecorder is used to record the audio and video, CamcorderProfile is
+ * used to configure the MediaRecorder. Preview is set to the video size.
+ * </p>
+ */
+ public void testPreviewSwitchBackFrontVideo() throws Exception {
+ List<String> mCameraColorOutputIds = cameraColorOutputCheck();
+ // Test iteration starts...
+ Log.i(TAG, "Testing preview switch back/front camera in video mode");
+ for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+ for (String id : mCameraColorOutputIds) {
+ try {
+ openDevice(id);
+ // Preview for basic video recording:
+ Log.v(TAG, String.format("Preview for recording videos: %d/%d", iteration + 1,
+ getIterationCount()));
+ recordingPreviewPreparer(id);
+ getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
+ } finally {
+ closeDevice();
+ releaseRecorder();
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Test back camera preview switch between still capture and recording mode.
+ * <p>
+ * This test covers the basic case of preview switch camera mode, between
+ * still capture (photo) and recording (video) mode. The preview settings
+ * are same with the settings in "testPreviewSwitchBackFrontCamera" and
+ * "testPreviewSwitchBackFrontVideo"
+ * </p>
+ */
+ public void testPreviewSwitchBackCameraVideo() throws Exception {
+ String id = mCameraIds[0];
+ openDevice(id);
+ if (!mStaticInfo.isColorOutputSupported()) {
+ Log.i(TAG, "Camera " + id +
+ " does not support color outputs, skipping");
+ return;
+ }
+ closeDevice();
+ // Test iteration starts...
+ Log.i(TAG, "Testing preview switch between still capture/video modes for back camera");
+ for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+ try {
+ openDevice(id);
+
+ // Preview for basic still capture:
+ Log.v(TAG, String.format("Preview pictures: %d/%d", iteration + 1,
+ getIterationCount()));
+ stillCapturePreviewPreparer(id);
+ getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
+
+ // Preview for basic video recording:
+ Log.v(TAG, String.format("Preview for recording videos: %d/%d", iteration + 1,
+ getIterationCount()));
+ recordingPreviewPreparer(id);
+ getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
+ } finally {
+ closeDevice();
+ closeImageReader();
+ }
+ }
+ }
+
+ /**
+ * Test front camera preview switch between still capture and recording mode.
+ * <p>
+ * This test covers the basic case of preview switch camera mode, between
+ * still capture (photo) and recording (video) mode. The preview settings
+ * are same with the settings in "testPreviewSwitchBackFrontCamera" and
+ * "testPreviewSwitchBackFrontVideo"
+ * </p>
+ */
+ public void testPreviewSwitchFrontCameraVideo() throws Exception{
+ String id = mCameraIds[1];
+ openDevice(id);
+ if (!mStaticInfo.isColorOutputSupported()) {
+ Log.i(TAG, "Camera " + id +
+ " does not support color outputs, skipping");
+ return;
+ }
+ closeDevice();
+ // Test iteration starts...
+ Log.i(TAG, "Testing preview switch between still capture/video modes for front camera");
+ for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+ try {
+ openDevice(id);
+
+ // Preview for basic still capture:
+ Log.v(TAG, String.format("Preview pictures: %d/%d", iteration + 1,
+ getIterationCount()));
+ stillCapturePreviewPreparer(id);
+ getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
+
+ // Preview for basic video recording:
+ Log.v(TAG, String.format("Preview for recording videos: %d/%d", iteration + 1,
+ getIterationCount()));
+ recordingPreviewPreparer(id);
+ getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
+ } finally {
+ closeDevice();
+ closeImageReader();
+ }
+ }
+ }
+
+ private void stillCapturePreviewPreparer(String id) throws Exception{
+ CaptureResult result;
+ SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+ SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
+ CaptureRequest.Builder previewRequest =
+ mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ CaptureRequest.Builder stillRequest =
+ mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+ // Preview Setup:
+ prepareCapturePreview(previewRequest, stillRequest, resultListener, imageListener);
+
+ Thread.sleep(getTestWaitIntervalMs());
+ }
+
+ private void recordingPreviewPreparer(String id) throws Exception{
+ // Re-use the MediaRecorder object for the same camera device.
+ mMediaRecorder = new MediaRecorder();
+ initSupportedVideoSize(id);
+ // preview Setup:
+ basicRecordingPreviewTestByCamera(mCamcorderProfileList);
+
+ Thread.sleep(getTestWaitIntervalMs());
+ }
+
+
+ /**
+ * Initialize the supported video sizes.
+ */
+ private void initSupportedVideoSize(String cameraId) throws Exception {
+ Size maxVideoSize = SIZE_BOUND_1080P;
+ if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_2160P)) {
+ maxVideoSize = SIZE_BOUND_2160P;
+ }
+ mSupportedVideoSizes =
+ getSupportedVideoSizes(cameraId, mCameraManager, maxVideoSize);
+ }
+
+
+ /**
+ * Test camera recording preview by using each available CamcorderProfile for a
+ * given camera. preview size is set to the video size.
+ */
+ private void basicRecordingPreviewTestByCamera(int[] camcorderProfileList)
+ throws Exception {
+ Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+ List<Range<Integer> > fpsRanges = Arrays.asList(
+ mStaticInfo.getAeAvailableTargetFpsRangesChecked());
+ int cameraId = Integer.parseInt(mCamera.getId());
+ int maxVideoFrameRate = -1;
+ int profileId = camcorderProfileList[0];
+ if (!CamcorderProfile.hasProfile(cameraId, profileId) ||
+ allowedUnsupported(cameraId, profileId)) {
+ return;
+ }
+
+ CamcorderProfile profile = CamcorderProfile.get(cameraId, profileId);
+ Size videoSz = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
+ Range<Integer> fpsRange = new Range(profile.videoFrameRate, profile.videoFrameRate);
+ if (maxVideoFrameRate < profile.videoFrameRate) {
+ maxVideoFrameRate = profile.videoFrameRate;
+ }
+ if (mStaticInfo.isHardwareLevelLegacy() &&
+ (videoSz.getWidth() > maxPreviewSize.getWidth() ||
+ videoSz.getHeight() > maxPreviewSize.getHeight())) {
+ // Skip. Legacy mode can only do recording up to max preview size
+ return;
+ }
+ assertTrue("Video size " + videoSz.toString() + " for profile ID " + profileId +
+ " must be one of the camera device supported video size!",
+ mSupportedVideoSizes.contains(videoSz));
+ assertTrue("Frame rate range " + fpsRange + " (for profile ID " + profileId +
+ ") must be one of the camera device available FPS range!",
+ fpsRanges.contains(fpsRange));
+
+ if (VERBOSE) {
+ Log.v(TAG, "Testing camera recording with video size " + videoSz.toString());
+ }
+
+ // Configure preview and recording surfaces.
+ mOutMediaFileName = VIDEO_FILE_PATH + "/test_video.mp4";
+ if (DEBUG_DUMP) {
+ mOutMediaFileName = VIDEO_FILE_PATH + "/test_video_" + cameraId + "_"
+ + videoSz.toString() + ".mp4";
+ }
+
+ prepareRecordingWithProfile(profile);
+
+ // prepare preview surface by using video size.
+ updatePreviewSurfaceWithVideo(videoSz, profile.videoFrameRate);
+
+ CaptureRequest.Builder previewRequest =
+ mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ CaptureRequest.Builder recordingRequest =
+ mCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
+
+ SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+ SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
+
+ prepareVideoPreview(previewRequest, recordingRequest, resultListener, imageListener);
+
+ // Can reuse the MediaRecorder object after reset.
+ mMediaRecorder.reset();
+
+ if (maxVideoFrameRate != -1) {
+ // At least one CamcorderProfile is present, check FPS
+ assertTrue("At least one CamcorderProfile must support >= 24 FPS",
+ maxVideoFrameRate >= 24);
+ }
+ }
+
+ private void releaseRecorder() {
+ if (mMediaRecorder != null) {
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+ }
+ }
+
+ private List<String> cameraColorOutputCheck() throws Exception {
+ List<String> mCameraColorOutputIds = new ArrayList<String>();
+ for (String id : mCameraIds) {
+ openDevice(id);
+ if (!mStaticInfo.isColorOutputSupported()) {
+ Log.i(TAG, "Camera " + id +
+ " does not support color outputs, skipping");
+ continue;
+ }
+ mCameraColorOutputIds.add(id);
+ closeDevice();
+ }
+ return mCameraColorOutputIds;
+ }
+
+ /**
+ * Returns {@code true} if the {@link CamcorderProfile} ID is allowed to be unsupported.
+ *
+ * <p>This only allows unsupported profiles when using the LEGACY mode of the Camera API.</p>
+ *
+ * @param profileId a {@link CamcorderProfile} ID to check.
+ * @return {@code true} if supported.
+ */
+ private boolean allowedUnsupported(int cameraId, int profileId) {
+ if (!mStaticInfo.isHardwareLevelLegacy()) {
+ return false;
+ }
+
+ switch(profileId) {
+ case CamcorderProfile.QUALITY_2160P:
+ case CamcorderProfile.QUALITY_1080P:
+ case CamcorderProfile.QUALITY_HIGH:
+ return !CamcorderProfile.hasProfile(cameraId, profileId) ||
+ CamcorderProfile.get(cameraId, profileId).videoFrameWidth >= 1080;
+ }
+ return false;
+ }
+
+ /**
+ * Configure MediaRecorder recording session with CamcorderProfile, prepare
+ * the recording surface.
+ */
+ private void prepareRecordingWithProfile(CamcorderProfile profile)
+ throws Exception {
+ // Prepare MediaRecorder.
+ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
+ mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
+ mMediaRecorder.setProfile(profile);
+ mMediaRecorder.setOutputFile(mOutMediaFileName);
+ if (mPersistentSurface != null) {
+ mMediaRecorder.setInputSurface(mPersistentSurface);
+ mRecordingSurface = mPersistentSurface;
+ }
+ mMediaRecorder.prepare();
+ if (mPersistentSurface == null) {
+ mRecordingSurface = mMediaRecorder.getSurface();
+ }
+ assertNotNull("Recording surface must be non-null!", mRecordingSurface);
+ mVideoFrameRate = profile.videoFrameRate;
+ mVideoSize = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
+ }
+
+ /**
+ * Update preview size with video size.
+ *
+ * <p>Preview size will be capped with max preview size.</p>
+ *
+ * @param videoSize The video size used for preview.
+ * @param videoFrameRate The video frame rate
+ *
+ */
+ private void updatePreviewSurfaceWithVideo(Size videoSize, int videoFrameRate) throws Exception {
+ if (mOrderedPreviewSizes == null) {
+ throw new IllegalStateException("supported preview size list is not initialized yet");
+ }
+ final float FRAME_DURATION_TOLERANCE = 0.01f;
+ long videoFrameDuration = (long) (1e9 / videoFrameRate *
+ (1.0 + FRAME_DURATION_TOLERANCE));
+ HashMap<Size, Long> minFrameDurationMap = mStaticInfo.
+ getAvailableMinFrameDurationsForFormatChecked(ImageFormat.PRIVATE);
+ Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+ Size previewSize = null;
+ if (videoSize.getWidth() > maxPreviewSize.getWidth() ||
+ videoSize.getHeight() > maxPreviewSize.getHeight()) {
+ for (Size s : mOrderedPreviewSizes) {
+ Long frameDuration = minFrameDurationMap.get(s);
+ if (mStaticInfo.isHardwareLevelLegacy()) {
+ // Legacy doesn't report min frame duration
+ frameDuration = new Long(0);
+ }
+ assertTrue("Cannot find minimum frame duration for private size" + s,
+ frameDuration != null);
+ if (frameDuration <= videoFrameDuration &&
+ s.getWidth() <= videoSize.getWidth() &&
+ s.getHeight() <= videoSize.getHeight()) {
+ Log.w(TAG, "Overwrite preview size from " + videoSize.toString() +
+ " to " + s.toString());
+ previewSize = s;
+ break;
+ // If all preview size doesn't work then we fallback to video size
+ }
+ }
+ }
+ if (previewSize == null) {
+ previewSize = videoSize;
+ }
+
+ updatePreviewSurface(previewSize);
+ }
+
+ protected void prepareVideoPreview(CaptureRequest.Builder previewRequest,
+ CaptureRequest.Builder recordingRequest,
+ CaptureCallback resultListener,
+ ImageReader.OnImageAvailableListener imageListener) throws Exception {
+
+ // Configure output streams with preview and jpeg streams.
+ List<Surface> outputSurfaces = new ArrayList<Surface>();
+ outputSurfaces.add(mPreviewSurface);
+ outputSurfaces.add(mRecordingSurface);
+
+ mSessionListener = new BlockingSessionCallback();
+ mSession = configureCameraSession(mCamera, outputSurfaces, mSessionListener, mHandler);
+
+ previewRequest.addTarget(mPreviewSurface);
+ recordingRequest.addTarget(mPreviewSurface);
+ recordingRequest.addTarget(mRecordingSurface);
+
+ // Start preview.
+ mSession.setRepeatingRequest(previewRequest.build(), null, mHandler);
+ }
+
+ protected void prepareCapturePreview(CaptureRequest.Builder previewRequest,
+ CaptureRequest.Builder stillRequest,
+ CaptureCallback resultListener,
+ ImageReader.OnImageAvailableListener imageListener) throws Exception {
+
+ Size captureSz = mOrderedStillSizes.get(0);
+ Size previewSz = mOrderedPreviewSizes.get(1);
+
+ if (VERBOSE) {
+ Log.v(TAG, String.format("Prepare single capture (%s) and preview (%s)",
+ captureSz.toString(), previewSz.toString()));
+ }
+
+ // Update preview size.
+ updatePreviewSurface(previewSz);
+
+ // Create ImageReader.
+ createImageReader(captureSz, ImageFormat.JPEG, MAX_READER_IMAGES, imageListener);
+
+ // Configure output streams with preview and jpeg streams.
+ List<Surface> outputSurfaces = new ArrayList<Surface>();
+ outputSurfaces.add(mPreviewSurface);
+ outputSurfaces.add(mReaderSurface);
+ mSessionListener = new BlockingSessionCallback();
+ mSession = configureCameraSession(mCamera, outputSurfaces, mSessionListener, mHandler);
+
+ // Configure the requests.
+ previewRequest.addTarget(mPreviewSurface);
+ stillRequest.addTarget(mPreviewSurface);
+ stillRequest.addTarget(mReaderSurface);
+
+ // Start preview.
+ mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);
+ }
+
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/Job.java b/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
index b4f1299..b8f8fba 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
@@ -308,7 +308,9 @@
String id, DocumentStack stack, List<DocumentInfo> srcs,
DocumentInfo srcParent) {
assert(!srcs.isEmpty());
- assert(stack.peek().isDirectory()); // we can't currently delete from archives.
+ // stack is empty if we delete docs from recent.
+ // we can't currently delete from archives.
+ assert(stack.isEmpty() || stack.peek().isDirectory());
return new DeleteJob(service, appContext, listener, id, stack, srcs, srcParent);
}
}
diff --git a/packages/PrintRecommendationService/res/values/donottranslate.xml b/packages/PrintRecommendationService/res/values/donottranslate.xml
index 68effbf..86027cd 100644
--- a/packages/PrintRecommendationService/res/values/donottranslate.xml
+++ b/packages/PrintRecommendationService/res/values/donottranslate.xml
@@ -32,8 +32,15 @@
<item>Hewlett Packard</item>
</string-array>
+ <string-array name="known_print_vendor_info_for_samsung" translatable="false">
+ <item>com.sec.app.samsungprintservice</item>
+ <item>Samsung Electronics</item>
+ <item>Samsung</item>
+ </string-array>
+
<array name="known_print_plugin_vendors" translatable="false">
<item>@array/known_print_vendor_info_for_mopria</item>
<item>@array/known_print_vendor_info_for_hp</item>
+ <item>@array/known_print_vendor_info_for_samsung</item>
</array>
</resources>
diff --git a/packages/PrintRecommendationService/res/values/strings.xml b/packages/PrintRecommendationService/res/values/strings.xml
index 97281de..348fcac 100644
--- a/packages/PrintRecommendationService/res/values/strings.xml
+++ b/packages/PrintRecommendationService/res/values/strings.xml
@@ -23,7 +23,7 @@
<string name="plugin_vendor_brother">Brother</string>
<string name="plugin_vendor_canon">Canon</string>
<string name="plugin_vendor_xerox">Xerox</string>
- <string name="plugin_vendor_samsung">Samsung Electronics</string>
+ <string name="plugin_vendor_samsung">Samsung</string>
<string name="plugin_vendor_epson">Epson</string>
<string name="plugin_vendor_konica_minolta">Konica Minolta</string>
<string name="plugin_vendor_fuji">Fuji</string>
diff --git a/packages/PrintRecommendationService/res/xml/vendorconfigs.xml b/packages/PrintRecommendationService/res/xml/vendorconfigs.xml
index b7925df..108ea66 100644
--- a/packages/PrintRecommendationService/res/xml/vendorconfigs.xml
+++ b/packages/PrintRecommendationService/res/xml/vendorconfigs.xml
@@ -51,14 +51,6 @@
</vendor>
<vendor>
- <name>@string/plugin_vendor_samsung</name>
- <package>com.sec.app.samsungprintservice</package>
- <mdns-names>
- <mdns-name>Samsung</mdns-name>
- </mdns-names>
- </vendor>
-
- <vendor>
<name>@string/plugin_vendor_epson</name>
<package>com.epson.mobilephone.android.epsonprintserviceplugin</package>
<mdns-names>
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
index 4b4b470..d95654f 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
@@ -25,6 +25,7 @@
import com.android.printservice.recommendation.plugin.mdnsFilter.MDNSFilterPlugin;
import com.android.printservice.recommendation.plugin.mdnsFilter.VendorConfig;
import com.android.printservice.recommendation.plugin.mopria.MopriaRecommendationPlugin;
+import com.android.printservice.recommendation.plugin.samsung.SamsungRecommendationPlugin;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
@@ -74,6 +75,14 @@
" plugin", e);
}
+ try {
+ mPlugins.add(new RemotePrintServicePlugin(new SamsungRecommendationPlugin(this), this,
+ false));
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Could not initiate " + getString(R.string.plugin_vendor_samsung) +
+ " plugin", e);
+ }
+
final int numPlugins = mPlugins.size();
for (int i = 0; i < numPlugins; i++) {
try {
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/MDnsUtils.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/MDnsUtils.java
new file mode 100644
index 0000000..963e09b
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/MDnsUtils.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 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.printservice.recommendation.plugin.samsung;
+
+import android.net.nsd.NsdServiceInfo;
+import android.text.TextUtils;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Locale;
+import java.util.Map;
+
+public class MDnsUtils {
+ public static final String ATTRIBUTE__TY = "ty";
+ public static final String ATTRIBUTE__PRODUCT = "product";
+ public static final String ATTRIBUTE__USB_MFG = "usb_MFG";
+ public static final String ATTRIBUTE__MFG = "mfg";
+
+ public static String getString(byte[] value) {
+ if (value != null) return new String(value,StandardCharsets.UTF_8);
+ return null;
+ }
+
+ public static boolean isVendorPrinter(NsdServiceInfo networkDevice, String[] vendorValues) {
+
+ Map<String,byte[]> attributes = networkDevice.getAttributes();
+ String product = getString(attributes.get(ATTRIBUTE__PRODUCT));
+ String ty = getString(attributes.get(ATTRIBUTE__TY));
+ String usbMfg = getString(attributes.get(ATTRIBUTE__USB_MFG));
+ String mfg = getString(attributes.get(ATTRIBUTE__MFG));
+ return containsVendor(product, vendorValues) || containsVendor(ty, vendorValues) || containsVendor(usbMfg, vendorValues) || containsVendor(mfg, vendorValues);
+
+ }
+
+ public static String getVendor(NsdServiceInfo networkDevice) {
+ String vendor;
+
+ Map<String,byte[]> attributes = networkDevice.getAttributes();
+ vendor = getString(attributes.get(ATTRIBUTE__MFG));
+ if (!TextUtils.isEmpty(vendor)) return vendor;
+ vendor = getString(attributes.get(ATTRIBUTE__USB_MFG));
+ if (!TextUtils.isEmpty(vendor)) return vendor;
+
+ return null;
+ }
+
+ private static boolean containsVendor(String container, String[] vendorValues) {
+ if ((container == null) || (vendorValues == null)) return false;
+ for (String value : vendorValues) {
+ if (containsString(container, value)
+ || containsString(container.toLowerCase(Locale.US), value.toLowerCase(Locale.US))
+ || containsString(container.toUpperCase(Locale.US), value.toUpperCase(Locale.US)))
+ return true;
+ }
+ return false;
+ }
+
+ private static boolean containsString(String container, String contained) {
+ return (container != null) && (contained != null) && (container.equalsIgnoreCase(contained) || container.contains(contained + " "));
+ }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterHashMap.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterHashMap.java
new file mode 100644
index 0000000..032fe22
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterHashMap.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 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.printservice.recommendation.plugin.samsung;
+
+import android.net.nsd.NsdServiceInfo;
+
+import java.util.HashMap;
+
+final class PrinterHashMap extends HashMap<String, NsdServiceInfo> {
+ public static String getKey(NsdServiceInfo serviceInfo) {
+ return serviceInfo.getServiceName();
+ }
+ public NsdServiceInfo addPrinter(NsdServiceInfo device) {
+ return put(getKey(device), device);
+ }
+ public NsdServiceInfo removePrinter(NsdServiceInfo device) {
+ return remove(getKey(device));
+ }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java
new file mode 100644
index 0000000..e5b8a0f
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java
@@ -0,0 +1,102 @@
+/*
+(c) Copyright 2016 Samsung Electronics..
+
+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.printservice.recommendation.plugin.samsung;
+
+import android.content.Context;
+import android.net.nsd.NsdServiceInfo;
+import android.text.TextUtils;
+
+import java.util.Locale;
+import java.util.Map;
+
+import com.android.printservice.recommendation.R;
+
+public class SamsungRecommendationPlugin extends ServiceRecommendationPlugin {
+
+ private static final String TAG = "SamsungRecommendation";
+
+ private static final String ATTR_USB_MFG = "usb_MFG";
+ private static final String ATTR_MFG = "mfg";
+ private static final String ATTR_USB_MDL = "usb_MDL";
+ private static final String ATTR_MDL = "mdl";
+ private static final String ATTR_PRODUCT = "product";
+ private static final String ATTR_TY = "ty";
+
+ private static String[] mNotSupportedDevices = new String[]{
+ "SCX-5x15",
+ "SF-555P",
+ "CF-555P",
+ "SCX-4x16",
+ "SCX-4214F",
+ "CLP-500",
+ "CJX-",
+ "MJC-"
+ };
+
+ private static boolean isSupportedModel(String model) {
+ if (!TextUtils.isEmpty(model)) {
+ String modelToUpper = model.toUpperCase(Locale.US);
+ for (String unSupportedPrinter : mNotSupportedDevices) {
+ if (modelToUpper.contains(unSupportedPrinter)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public SamsungRecommendationPlugin(Context context) {
+ super(context, R.string.plugin_vendor_samsung, new VendorInfo(context.getResources(), R.array.known_print_vendor_info_for_samsung), new String[]{"_pdl-datastream._tcp"});
+ }
+
+ @Override
+ public boolean matchesCriteria(String vendor, NsdServiceInfo nsdServiceInfo) {
+ if (!TextUtils.equals(vendor, mVendorInfo.mVendorID)) return false;
+
+ String modelName = getModelName(nsdServiceInfo);
+ if (modelName != null) {
+ return (isSupportedModel(modelName));
+ }
+ return false;
+ }
+
+ private String getModelName(NsdServiceInfo resolvedDevice) {
+ Map<String,byte[]> attributes = resolvedDevice.getAttributes();
+ String usb_mfg = MDnsUtils.getString(attributes.get(ATTR_USB_MFG));
+ if (TextUtils.isEmpty(usb_mfg)) {
+ usb_mfg = MDnsUtils.getString(attributes.get(ATTR_MFG));
+ }
+
+ String usb_mdl = MDnsUtils.getString(attributes.get(ATTR_USB_MDL));
+ if (TextUtils.isEmpty(usb_mdl)) {
+ usb_mdl = MDnsUtils.getString(attributes.get(ATTR_MDL));
+ }
+
+ String modelName = null;
+ if (!TextUtils.isEmpty(usb_mfg) && !TextUtils.isEmpty(usb_mdl)) {
+ modelName = usb_mfg.trim() + " " + usb_mdl.trim();
+ } else {
+ modelName = MDnsUtils.getString(attributes.get(ATTR_PRODUCT));
+ if (TextUtils.isEmpty(modelName)) {
+ modelName = MDnsUtils.getString(attributes.get(ATTR_TY));
+ }
+ }
+
+ return modelName;
+ }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceListener.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceListener.java
new file mode 100644
index 0000000..7bb83c9
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceListener.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2016 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.printservice.recommendation.plugin.samsung;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
+import android.text.TextUtils;
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.android.printservice.recommendation.R;
+import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer;
+
+public class ServiceListener implements ServiceResolveQueue.ResolveCallback {
+
+ private final NsdManager mNSDManager;
+ private final Map<String, VendorInfo> mVendorInfoHashMap;
+ private final String[] mServiceType;
+ private final Observer mObserver;
+ private final ServiceResolveQueue mResolveQueue;
+ private List<NsdManager.DiscoveryListener> mListeners = new ArrayList<>();
+ public HashMap<String, PrinterHashMap> mVendorHashMap = new HashMap<>();
+
+ public interface Observer {
+ boolean matchesCriteria(String vendor, NsdServiceInfo serviceInfo);
+ void dataSetChanged();
+ }
+
+ public ServiceListener(Context context, Observer observer, String[] serviceTypes) {
+ mObserver = observer;
+ mServiceType = serviceTypes;
+ mNSDManager = (NsdManager)context.getSystemService(Context.NSD_SERVICE);
+ mResolveQueue = ServiceResolveQueue.getInstance(mNSDManager);
+
+ Map<String, VendorInfo> vendorInfoMap = new HashMap<>();
+ TypedArray testArray = context.getResources().obtainTypedArray(R.array.known_print_plugin_vendors);
+ for(int i = 0; i < testArray.length(); i++) {
+ int arrayID = testArray.getResourceId(i, 0);
+ if (arrayID != 0) {
+ VendorInfo info = new VendorInfo(context.getResources(), arrayID);
+ vendorInfoMap.put(info.mVendorID, info);
+ vendorInfoMap.put(info.mPackageName, info);
+ }
+ }
+ testArray.recycle();
+ mVendorInfoHashMap = vendorInfoMap;
+ }
+
+ @Override
+ public void serviceResolved(NsdServiceInfo nsdServiceInfo) {
+ printerFound(nsdServiceInfo);
+ }
+
+ private synchronized void printerFound(NsdServiceInfo nsdServiceInfo) {
+ if (nsdServiceInfo == null) return;
+ if (TextUtils.isEmpty(PrinterHashMap.getKey(nsdServiceInfo))) return;
+ String vendor = MDnsUtils.getVendor(nsdServiceInfo);
+ if (vendor == null) vendor = "";
+ for(Map.Entry<String,VendorInfo> entry : mVendorInfoHashMap.entrySet()) {
+ for(String vendorValues : entry.getValue().mDNSValues) {
+ if (vendor.equalsIgnoreCase(vendorValues)) {
+ vendor = entry.getValue().mVendorID;
+ break;
+ }
+ }
+ // intentional pointer check
+ //noinspection StringEquality
+ if ((vendor != entry.getValue().mVendorID) &&
+ MDnsUtils.isVendorPrinter(nsdServiceInfo, entry.getValue().mDNSValues)) {
+ vendor = entry.getValue().mVendorID;
+ }
+ // intentional pointer check
+ //noinspection StringEquality
+ if (vendor == entry.getValue().mVendorID) break;
+ }
+
+ if (TextUtils.isEmpty(vendor)) {
+ return;
+ }
+
+ if (!mObserver.matchesCriteria(vendor, nsdServiceInfo))
+ return;
+ boolean mapsChanged;
+
+ PrinterHashMap vendorHash = mVendorHashMap.get(vendor);
+ if (vendorHash == null) {
+ vendorHash = new PrinterHashMap();
+ }
+ mapsChanged = (vendorHash.addPrinter(nsdServiceInfo) == null);
+ mVendorHashMap.put(vendor, vendorHash);
+
+ if (mapsChanged) {
+ mObserver.dataSetChanged();
+ }
+ }
+
+ private synchronized void printerRemoved(NsdServiceInfo nsdServiceInfo) {
+ boolean wasRemoved = false;
+ Set<String> vendors = mVendorHashMap.keySet();
+ for(String vendor : vendors) {
+ PrinterHashMap map = mVendorHashMap.get(vendor);
+ wasRemoved |= (map.removePrinter(nsdServiceInfo) != null);
+ if (map.isEmpty()) wasRemoved |= (mVendorHashMap.remove(vendor) != null);
+ }
+ if (wasRemoved) {
+ mObserver.dataSetChanged();
+ }
+ }
+
+ public void start() {
+ stop();
+ for(final String service :mServiceType) {
+ NsdManager.DiscoveryListener listener = new NsdManager.DiscoveryListener() {
+ @Override
+ public void onStartDiscoveryFailed(String s, int i) {
+
+ }
+
+ @Override
+ public void onStopDiscoveryFailed(String s, int i) {
+
+ }
+
+ @Override
+ public void onDiscoveryStarted(String s) {
+
+ }
+
+ @Override
+ public void onDiscoveryStopped(String s) {
+
+ }
+
+ @Override
+ public void onServiceFound(NsdServiceInfo nsdServiceInfo) {
+ mResolveQueue.queueRequest(nsdServiceInfo, ServiceListener.this);
+ }
+
+ @Override
+ public void onServiceLost(NsdServiceInfo nsdServiceInfo) {
+ mResolveQueue.removeRequest(nsdServiceInfo, ServiceListener.this);
+ printerRemoved(nsdServiceInfo);
+ }
+ };
+ DiscoveryListenerMultiplexer.addListener(mNSDManager, service, listener);
+ mListeners.add(listener);
+ }
+ }
+
+ public void stop() {
+ for(NsdManager.DiscoveryListener listener : mListeners) {
+ DiscoveryListenerMultiplexer.removeListener(mNSDManager, listener);
+ }
+ mVendorHashMap.clear();
+ mListeners.clear();
+ }
+
+ public Pair<Integer, Integer> getCount() {
+ int count = 0;
+ for (PrinterHashMap map : mVendorHashMap.values()) {
+ count += map.size();
+ }
+ return Pair.create(mVendorHashMap.size(), count);
+ }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceRecommendationPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceRecommendationPlugin.java
new file mode 100644
index 0000000..9d15f30
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceRecommendationPlugin.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 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.printservice.recommendation.plugin.samsung;
+
+import android.content.Context;
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
+import android.annotation.NonNull;
+import android.text.TextUtils;
+import com.android.printservice.recommendation.PrintServicePlugin;
+
+public abstract class ServiceRecommendationPlugin implements PrintServicePlugin, ServiceListener.Observer {
+
+ protected static final String PDL_ATTRIBUTE = "pdl";
+
+ protected final Object mLock = new Object();
+ protected PrinterDiscoveryCallback mCallback = null;
+ protected final ServiceListener mListener;
+ protected final NsdManager mNSDManager;
+ protected final VendorInfo mVendorInfo;
+ private final int mVendorStringID;
+
+ protected ServiceRecommendationPlugin(Context context, int vendorStringID, VendorInfo vendorInfo, String[] services) {
+ mNSDManager = (NsdManager)context.getSystemService(Context.NSD_SERVICE);
+ mVendorStringID = vendorStringID;
+ mVendorInfo = vendorInfo;
+ mListener = new ServiceListener(context, this, services);
+ }
+
+ @Override
+ public int getName() {
+ return mVendorStringID;
+ }
+
+ @NonNull
+ @Override
+ public CharSequence getPackageName() {
+ return mVendorInfo.mPackageName;
+ }
+
+ @Override
+ public void start(@NonNull PrinterDiscoveryCallback callback) throws Exception {
+ synchronized (mLock) {
+ mCallback = callback;
+ }
+ mListener.start();
+ }
+
+ @Override
+ public void stop() throws Exception {
+ synchronized (mLock) {
+ mCallback = null;
+ }
+ mListener.stop();
+ }
+
+ @Override
+ public void dataSetChanged() {
+ synchronized (mLock) {
+ if (mCallback != null) mCallback.onChanged(getCount());
+ }
+ }
+
+ @Override
+ public boolean matchesCriteria(String vendor, NsdServiceInfo nsdServiceInfo) {
+ return TextUtils.equals(vendor, mVendorInfo.mVendorID);
+ }
+
+ public int getCount() {
+ return mListener.getCount().second;
+ }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceResolveQueue.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceResolveQueue.java
new file mode 100644
index 0000000..e5691b7
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceResolveQueue.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 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.printservice.recommendation.plugin.samsung;
+
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
+import android.util.Pair;
+import com.android.printservice.recommendation.util.NsdResolveQueue;
+
+import java.util.LinkedList;
+
+final class ServiceResolveQueue {
+
+ private final NsdManager mNsdManager;
+ private final LinkedList<Pair<NsdServiceInfo, ResolveCallback>> mQueue = new LinkedList<>();
+ private final Object mLock = new Object();
+
+ private static Object sLock = new Object();
+ private static ServiceResolveQueue sInstance = null;
+ private final NsdResolveQueue mNsdResolveQueue;
+ private Pair<NsdServiceInfo, ResolveCallback> mCurrentRequest = null;
+
+ public static void createInstance(NsdManager nsdManager) {
+ if (sInstance == null) sInstance = new ServiceResolveQueue(nsdManager);
+ }
+
+ public static ServiceResolveQueue getInstance(NsdManager nsdManager) {
+ synchronized (sLock) {
+ createInstance(nsdManager);
+ return sInstance;
+ }
+ }
+
+ public static void destroyInstance() {
+ sInstance = null;
+ }
+
+ public interface ResolveCallback {
+ void serviceResolved(NsdServiceInfo nsdServiceInfo);
+ }
+
+ public ServiceResolveQueue(NsdManager nsdManager) {
+ mNsdManager = nsdManager;
+ mNsdResolveQueue = NsdResolveQueue.getInstance();
+ }
+
+ public void queueRequest(NsdServiceInfo serviceInfo, ResolveCallback callback) {
+ synchronized (mLock) {
+ Pair<NsdServiceInfo, ResolveCallback> newRequest = Pair.create(serviceInfo, callback);
+ if (mQueue.contains(newRequest)) return;
+ mQueue.add(newRequest);
+ makeNextRequest();
+ }
+ }
+
+ public void removeRequest(NsdServiceInfo serviceInfo, ResolveCallback callback) {
+ synchronized (mLock) {
+ Pair<NsdServiceInfo, ResolveCallback> newRequest = Pair.create(serviceInfo, callback);
+ mQueue.remove(newRequest);
+ if ((mCurrentRequest != null) && newRequest.equals(mCurrentRequest)) mCurrentRequest = null;
+ }
+ }
+
+ private void makeNextRequest() {
+ synchronized (mLock) {
+ if (mCurrentRequest != null) return;
+ if (mQueue.isEmpty()) return;
+ mCurrentRequest = mQueue.removeFirst();
+ mNsdResolveQueue.resolve(mNsdManager, mCurrentRequest.first,
+ new NsdManager.ResolveListener() {
+ @Override
+ public void onResolveFailed(NsdServiceInfo nsdServiceInfo, int i) {
+ synchronized (mLock) {
+ if (mCurrentRequest != null) mQueue.add(mCurrentRequest);
+ makeNextRequest();
+ }
+ }
+
+ @Override
+ public void onServiceResolved(NsdServiceInfo nsdServiceInfo) {
+ synchronized (mLock) {
+ if (mCurrentRequest != null) {
+ mCurrentRequest.second.serviceResolved(nsdServiceInfo);
+ mCurrentRequest = null;
+ }
+ makeNextRequest();
+ }
+ }
+ });
+
+ }
+ }
+
+
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/VendorInfo.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/VendorInfo.java
new file mode 100644
index 0000000..0ebb4e4
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/VendorInfo.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 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.printservice.recommendation.plugin.samsung;
+
+import android.content.res.Resources;
+
+import java.util.Arrays;
+
+public final class VendorInfo {
+
+ public final String mPackageName;
+ public final String mVendorID;
+ public final String[] mDNSValues;
+ public final int mID;
+
+ public VendorInfo(Resources resources, int vendor_info_id) {
+ mID = vendor_info_id;
+ String[] data = resources.getStringArray(vendor_info_id);
+ if ((data == null) || (data.length < 2)) {
+ data = new String[] { null, null };
+ }
+ mPackageName = data[0];
+ mVendorID = data[1];
+ mDNSValues = (data.length > 2) ? Arrays.copyOfRange(data, 2, data.length) : new String[]{};
+ }
+}
diff --git a/packages/PrintSpooler/res/layout/add_printer_list_header.xml b/packages/PrintSpooler/res/layout/add_printer_list_header.xml
index 9eee0c4..488b3ab 100644
--- a/packages/PrintSpooler/res/layout/add_printer_list_header.xml
+++ b/packages/PrintSpooler/res/layout/add_printer_list_header.xml
@@ -24,6 +24,7 @@
android:gravity="start|center_vertical">
<TextView android:id="@+id/text"
- style="?android:attr/listSeparatorTextViewStyle" />
+ style="?android:attr/listSeparatorTextViewStyle"
+ android:textAlignment="viewStart" />
</LinearLayout>
diff --git a/packages/SettingsLib/res/drawable/notification_auto_importance.xml b/packages/SettingsLib/res/drawable/notification_auto_importance.xml
index a63e911b..c946153 100644
--- a/packages/SettingsLib/res/drawable/notification_auto_importance.xml
+++ b/packages/SettingsLib/res/drawable/notification_auto_importance.xml
@@ -20,8 +20,8 @@
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M11.2,13.6l1.6,0l-0.8,-2.6z"/>
+ android:pathData="M10.8,12.7l2.4,0l-1.2,-3.7z"/>
<path
android:fillColor="#FF000000"
- android:pathData="M22.5,9.6L15,9l-3,-7L9,9L1.5,9.6l5.7,5L5.5,22l6.5,-3.9l6.5,3.9l-1.7,-7.4L22.5,9.6zM13.6,16l-0.5,-1.4h-2.3L10.4,16H9l2.3,-6.4h1.4L15,16H13.6z"/>
+ android:pathData="M12,2C6.5,2 2,6.5 2,12s4.5,10 10,10s10,-4.5 10,-10S17.5,2 12,2zM14.3,16l-0.7,-2h-3.2l-0.7,2H7.8L11,7h2l3.2,9H14.3z"/>
</vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index fe726264..eae49c4 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Geaktiveer deur administrateur"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Gedeaktiveer deur administrateur"</string>
<string name="home" msgid="3256884684164448244">"Instellingstuisblad"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> gelede"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> oor"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Klein"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 843db18..4fd4259 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"በአስተዳዳሪ የነቃ"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"በአስተዳዳሪ የተሰናከለ"</string>
<string name="home" msgid="3256884684164448244">"የቅንብሮች መነሻ"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"ከ<xliff:g id="ID_1">%1$s</xliff:g> በፊት"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ቀርቷል"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"ትንሽ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 27050d1..246880c 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"تم التمكين بواسطة المشرف"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"تم التعطيل بواسطة المشرف"</string>
<string name="home" msgid="3256884684164448244">"الشاشة الرئيسية للإعدادات"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"٠٪"</item>
+ <item msgid="8934126114226089439">"٪۵۰"</item>
+ <item msgid="1286113608943010849">"٪۱۰۰"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"قبل <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"يتبقى <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"صغير"</string>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index 414bcd4..0caeea0 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Administrator tərəfindən aktiv edildi"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Administrator tərəfindən deaktiv edildi"</string>
<string name="home" msgid="3256884684164448244">"Ayarların əsas səhifəsi"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> əvvəl"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> qalıb"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Kiçik"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 2239dee..a61462d 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Omogućio je administrator"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Onemogućio je administrator"</string>
<string name="home" msgid="3256884684164448244">"Početna za Podešavanja"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Pre <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Još <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Mali"</string>
diff --git a/packages/SettingsLib/res/values-be-rBY/strings.xml b/packages/SettingsLib/res/values-be-rBY/strings.xml
index 7e13220..0637741 100644
--- a/packages/SettingsLib/res/values-be-rBY/strings.xml
+++ b/packages/SettingsLib/res/values-be-rBY/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Уключана адміністратарам"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Адключана адміністратарам"</string>
<string name="home" msgid="3256884684164448244">"Галоўная старонка налад"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> таму назад"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Засталося <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Маленькі"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index b410590..efc88ca 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Активирано от администратора"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Деактивирано от администратора"</string>
<string name="home" msgid="3256884684164448244">"Начален екран на Настройки"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Преди <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Оставащо време: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Малко"</string>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index 2019097..791c527 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"প্রশাসক সক্ষম করেছেন"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"প্রশাসক অক্ষম করেছেন"</string>
<string name="home" msgid="3256884684164448244">"সেটিংস হোম"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"০%"</item>
+ <item msgid="8934126114226089439">"৫০%"</item>
+ <item msgid="1286113608943010849">"১০০%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> আগে"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> বাকী আছে"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"ক্ষুদ্র"</string>
diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml
index 995d8562..28e3507 100644
--- a/packages/SettingsLib/res/values-bs-rBA/strings.xml
+++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Omogućio administrator"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Onemogućio je administrator"</string>
<string name="home" msgid="3256884684164448244">"Postavke početne stranice"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"prije <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Još otprilike <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Malo"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index ef52df5..2487313 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Opció activada per l\'administrador"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Opció desactivada per l\'administrador"</string>
<string name="home" msgid="3256884684164448244">"Pàgina d\'inici de configuració"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Fa <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Temps restant: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Petit"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index bb0b608..42c7bdf 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Povoleno administrátorem"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Zakázáno administrátorem"</string>
<string name="home" msgid="3256884684164448244">"Domovská stránka Nastavení"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0 %"</item>
+ <item msgid="8934126114226089439">"50 %"</item>
+ <item msgid="1286113608943010849">"100 %"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"před <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Zbývající čas: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Malé"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index df024c3..4df39d2 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Aktiveret af administratoren"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Deaktiveret af administratoren"</string>
<string name="home" msgid="3256884684164448244">"Startside for Indstillinger"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0 %"</item>
+ <item msgid="8934126114226089439">"50 %"</item>
+ <item msgid="1286113608943010849">"100 %"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> siden"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> tilbage"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Lille"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 16b6ace..169d6b0 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Vom Administrator aktiviert"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Vom Administrator deaktiviert"</string>
<string name="home" msgid="3256884684164448244">"Startseite \"Einstellungen\""</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0 %"</item>
+ <item msgid="8934126114226089439">"50 %"</item>
+ <item msgid="1286113608943010849">"100 %"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Vor <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Noch <xliff:g id="ID_1">%1$s</xliff:g> verbleibend"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Klein"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 7827ab9..c525145 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Ενεργοποιήθηκε από το διαχειριστή"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Απενεργοποιήθηκε από το διαχειριστή"</string>
<string name="home" msgid="3256884684164448244">"Αρχική σελίδα ρυθμίσεων"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Πριν από <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Απομένουν <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Μικρά"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index ec3d04b..05fc9db 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Enabled by administrator"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Disabled by administrator"</string>
<string name="home" msgid="3256884684164448244">"Settings Home"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ago"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> left"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Small"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index ec3d04b..05fc9db 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Enabled by administrator"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Disabled by administrator"</string>
<string name="home" msgid="3256884684164448244">"Settings Home"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ago"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> left"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Small"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index ec3d04b..05fc9db 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Enabled by administrator"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Disabled by administrator"</string>
<string name="home" msgid="3256884684164448244">"Settings Home"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ago"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> left"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Small"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 2facecb..2fd5e9b 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Habilitada por el administrador"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Inhabilitada por el administrador"</string>
<string name="home" msgid="3256884684164448244">"Pantalla de configuración"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Hace <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Falta <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Pequeño"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 163e846..b4e0125 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Habilitado por el administrador"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Inhabilitado por el administrador"</string>
<string name="home" msgid="3256884684164448244">"Página principal de ajustes"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Hace <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Tiempo restante: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Pequeño"</string>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index 756e4ad..cda3d9f 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Administraator on lubanud"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Administraator on keelanud"</string>
<string name="home" msgid="3256884684164448244">"Seadete avaleht"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> tagasi"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> on jäänud"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Väike"</string>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index b6db37a..00a92e8 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Administratzaileak gaitu du"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Administratzaileak desgaitu du"</string>
<string name="home" msgid="3256884684164448244">"Ezarpenen orri nagusia"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"% 0"</item>
+ <item msgid="8934126114226089439">"% 50"</item>
+ <item msgid="1286113608943010849">"% 100"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Duela <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> guztiz kargatu arte"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Txikia"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 2f0f8c8..8729ffd 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"سرپرست آن را فعال کرده است"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"سرپرست آن را غیرفعال کرده است"</string>
<string name="home" msgid="3256884684164448244">"صفحه اصلی تنظیمات"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"٪۰"</item>
+ <item msgid="8934126114226089439">"۵۰٪"</item>
+ <item msgid="1286113608943010849">"۱۰۰٪"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> قبل"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> باقی مانده است"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"کوچک"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 1f2579b..5c4287a 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Järjestelmänvalvojan käyttöön ottama"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Järjestelmänvalvojan käytöstä poistama"</string>
<string name="home" msgid="3256884684164448244">"Asetusten etusivu"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0 %"</item>
+ <item msgid="8934126114226089439">"50 %"</item>
+ <item msgid="1286113608943010849">"100 %"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> sitten"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> jäljellä"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Pieni"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 2ada136..6f7982d 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Activé par l\'administrateur"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Désactivé par l\'administrateur"</string>
<string name="home" msgid="3256884684164448244">"Accueil des paramètres"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0 %"</item>
+ <item msgid="8934126114226089439">"50 %"</item>
+ <item msgid="1286113608943010849">"100 %"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Il y a <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Durée restante :<xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Petite"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index ac8f629..a72ecd6 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Activé par l\'administrateur"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Désactivé par l\'administrateur"</string>
<string name="home" msgid="3256884684164448244">"Paramètres"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0 %"</item>
+ <item msgid="8934126114226089439">"50 %"</item>
+ <item msgid="1286113608943010849">"100 %"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Il y a <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Il reste <xliff:g id="ID_1">%1$s</xliff:g>."</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Petit"</string>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index ce52a70..8fb4431 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Activado polo administrador"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Desactivado polo administrador"</string>
<string name="home" msgid="3256884684164448244">"Inicio da configuración"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0 %"</item>
+ <item msgid="8934126114226089439">"50 %"</item>
+ <item msgid="1286113608943010849">"100 %"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Hai <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Tempo restante: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Pequeno"</string>
diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml
index 13eb654..fcb3968 100644
--- a/packages/SettingsLib/res/values-gu-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"વ્યવસ્થાપક દ્વારા સક્ષમ કરેલ"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ"</string>
<string name="home" msgid="3256884684164448244">"સેટિંગ્સ હોમ"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> પહેલાં"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> બાકી"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"નાનું"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 0ed67ee..65338cc 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"व्यवस्थापक द्वारा सक्षम किया गया"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"व्यवस्थापक द्वारा अक्षम किया गया"</string>
<string name="home" msgid="3256884684164448244">"सेटिंग होम"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> पहले"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> शेष"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"छोटा"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 6c87e80..148065e 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Omogućio administrator"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Onemogućio administrator"</string>
<string name="home" msgid="3256884684164448244">"Početni zaslon postavki"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Prije <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Još <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Malo"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 5b8525c..d8af0d4 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Engedélyezve a rendszergazda által"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Letiltva a rendszergazda által"</string>
<string name="home" msgid="3256884684164448244">"Kezdőlap beállítása"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Ennyi ideje: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> van hátra"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Kicsi"</string>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 8db93c6..36eafa5 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Միացված է ադմինիստրատորի կողմից"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Կասեցված է ադմինիստրատորի կողմից"</string>
<string name="home" msgid="3256884684164448244">"Կարգավորումների գլխավոր էջ"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> առաջ"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Մնացել է <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Փոքր"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index e328a93..acbbb4c 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Diaktifkan oleh administrator"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Dinonaktifkan oleh administrator"</string>
<string name="home" msgid="3256884684164448244">"Layar Utama Setelan"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> lalu"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Tersisa <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Kecil"</string>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index 3558270..4bfc0a6 100644
--- a/packages/SettingsLib/res/values-is-rIS/strings.xml
+++ b/packages/SettingsLib/res/values-is-rIS/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Virkjað af stjórnanda"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Stjórnandi gerði óvirkt"</string>
<string name="home" msgid="3256884684164448244">"Stillingar"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Fyrir <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> eftir"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Lítið"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 4c99887..959b661 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Attivata dall\'amministratore"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Disattivata dall\'amministratore"</string>
<string name="home" msgid="3256884684164448244">"Home page Impostazioni"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%%"</item>
+ <item msgid="8934126114226089439">"50%%"</item>
+ <item msgid="1286113608943010849">"100%%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> fa"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> rimanenti"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Piccolo"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 7574322..44016ef 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"הופעל על ידי מנהל המערכת"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"הושבת על ידי מנהל המערכת"</string>
<string name="home" msgid="3256884684164448244">"דף הבית של ההגדרות"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"לפני <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"נשארו <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"קטן"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index b25ad19..12c5e25 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -326,6 +326,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"管理者によって有効にされています"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"管理者によって無効にされています"</string>
<string name="home" msgid="3256884684164448244">"設定のホーム"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"あと <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"小"</string>
diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml
index 1edca1b..eacc4f5 100644
--- a/packages/SettingsLib/res/values-ka-rGE/strings.xml
+++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"ჩართულია ადმინისტრატორის მიერ"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"გათიშულია ადმინისტრატორის მიერ"</string>
<string name="home" msgid="3256884684164448244">"პარამეტრების მთავარი გვერდი"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"გავიდა <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"დარჩენილია <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"პატარა"</string>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index 5100282..a8631ee 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Әкімші қосқан"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Әкімші өшірген"</string>
<string name="home" msgid="3256884684164448244">"Параметрлер негізгі беті"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> бұрын"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> қалды"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Кішкентай"</string>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index 941c01d..a240a37 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"បានបើកដំណើរការដោយអ្នកគ្រប់គ្រង"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"បានបិទដំណើរការដោយអ្នកគ្រប់គ្រង"</string>
<string name="home" msgid="3256884684164448244">"ទំព័រដើមនៃការកំណត់"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> មុន"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"នៅសល់ <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"តូច"</string>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index 99fb1b2..170a928 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"ನಿರ್ವಾಹಕರಿಂದ ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"ನಿರ್ವಾಹಕರಿಂದ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="home" msgid="3256884684164448244">"ಸೆಟ್ಟಿಂಗ್ಗಳ ಮುಖಪುಟ"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ಹಿಂದೆ"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ಉಳಿದಿದೆ"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"ಸಣ್ಣದು"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 0f48a45..dace41b 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"관리자가 사용 설정함"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"관리자가 사용 중지함"</string>
<string name="home" msgid="3256884684164448244">"설정 홈"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> 전"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> 남음"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"작게"</string>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index 935d0b3..e1cfc60 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Администратор иштетип койгон"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Администратор өчүрүп койгон"</string>
<string name="home" msgid="3256884684164448244">"Жөндөөлөрдүн башкы бети"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> мурун"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> калды"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Кичине"</string>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index d768214..b7befd6 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"ຖືກເປີດໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບ"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"ຖືກປິດໄວ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບ"</string>
<string name="home" msgid="3256884684164448244">"ໜ້າທຳອິດຂອງການຕັ້ງຄ່າ"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ກ່ອນນີ້"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"ຍັງເຫຼືອ <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"ນ້ອຍ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 7318b41..d409366 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Įgalino administratorius"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Išjungė administratorius"</string>
<string name="home" msgid="3256884684164448244">"Pagrindinis Nustatymų ekranas"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0 %"</item>
+ <item msgid="8934126114226089439">"50 %"</item>
+ <item msgid="1286113608943010849">"100 %"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Prieš <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Liko <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Mažas"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index e11a4b2..7dfd9ac 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Iespējojis administrators"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Atspējojis administrators"</string>
<string name="home" msgid="3256884684164448244">"Iestatījumu sākumekrāns"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Pirms šāda laika: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Atlikušais laiks: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Mazs"</string>
diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml
index f0d7e12..7f3f17a 100644
--- a/packages/SettingsLib/res/values-mk-rMK/strings.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Овозможено од администраторот"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Оневозможено од администраторот"</string>
<string name="home" msgid="3256884684164448244">"Почетна страница за поставки"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Пред <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Преостанаа <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Мал"</string>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index 82ef83d..80ff8c3 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"അഡ്മിനിസ്ട്രേറ്റർ പ്രവർത്തനക്ഷമമാക്കി"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"അഡ്മിനിസ്ട്രേറ്റർ പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="home" msgid="3256884684164448244">"ക്രമീകരണ ഹോം"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> മുമ്പ്"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"ചെറുത്"</string>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index 0757508..359c041 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Админ идэвхтэй болгосон"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Админ идэвхгүй болгосон"</string>
<string name="home" msgid="3256884684164448244">"Тохиргооны нүүр хуудас"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> өмнө"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> үлдсэн"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Жижиг"</string>
diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml
index ba020da..1d5dc19 100644
--- a/packages/SettingsLib/res/values-mr-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"प्रशासकाने सक्षम केलेले"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"प्रशासकाने अक्षम केलेले"</string>
<string name="home" msgid="3256884684164448244">"सेटिंग्ज मुख्यपृष्ठ"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> पूर्वी"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> शिल्लक"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"लहान"</string>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index 554b3af..8809f71 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Didayakan oleh pentadbir"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Dilumpuhkan oleh pentadbir"</string>
<string name="home" msgid="3256884684164448244">"Laman Utama Tetapan"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> yang lalu"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> lagi"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Kecil"</string>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index 1a4b687..9bb5694 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"စီမံခန့်ခွဲသူမှ ဖွင့်ထားသည်"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"စီမံခန့်ခွဲသူမှ ပိတ်ထားသည်"</string>
<string name="home" msgid="3256884684164448244">"ဆက်တင် ပင်မစာမျက်နှာ"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"၀%"</item>
+ <item msgid="8934126114226089439">"၅၀%"</item>
+ <item msgid="1286113608943010849">"၁၀၀%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"ပြီးခဲ့သည့် <xliff:g id="ID_1">%1$s</xliff:g> က"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ကျန်ပါသည်"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"သေး"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index fa15cd3..1c13fc3 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -70,7 +70,7 @@
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Bruk til filoverføring"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Bruk for inndata"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sammenkoble"</string>
- <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"KOBLE"</string>
+ <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"KOBLE TIL"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Avbryt"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Med sammenkobling får den andre enheten tilgang til kontaktene og anropsloggen din når den er tilkoblet."</string>
<string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Kan ikke koble til <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Slått på av administratoren"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Avslått av administratoren"</string>
<string name="home" msgid="3256884684164448244">"Innstillinger for startsiden"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0 %"</item>
+ <item msgid="8934126114226089439">"50 %"</item>
+ <item msgid="1286113608943010849">"100 %"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> siden"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> gjenstår"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Liten"</string>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index e091138..8faccf5 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"प्रशासकद्वारा सक्षम गरिएको छ"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"प्रशासकद्वारा असक्षम गरिएको छ"</string>
<string name="home" msgid="3256884684164448244">"सेटिङहरूको गृहपृष्ठ"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"०%"</item>
+ <item msgid="8934126114226089439">"५०%"</item>
+ <item msgid="1286113608943010849">"१००%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> पहिले"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> बाँकी"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"सानो"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 2c2c5d0..b080131 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Ingeschakeld door beheerder"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Uitgeschakeld door beheerder"</string>
<string name="home" msgid="3256884684164448244">"Startpagina voor instellingen"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> geleden"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> resterend"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Klein"</string>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index fb17b6c..dba71c3 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਯੋਗ ਬਣਾਈ ਗਈ"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਅਯੋਗ ਬਣਾਈ ਗਈ"</string>
<string name="home" msgid="3256884684164448244">"ਸੈਟਿੰਗਾਂ ਮੁੱਖ ਪੰਨਾ"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ਪਹਿਲਾਂ"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ਬਾਕੀ"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"ਛੋਟਾ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index e0c51f1..c72f0c6 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Włączone przez administratora"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Wyłączone przez administratora"</string>
<string name="home" msgid="3256884684164448244">"Ekran główny ustawień"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> temu"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Pozostało <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Mały"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index b2ca437..d01ddb7 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Ativada pelo administrador"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Desativada pelo administrador"</string>
<string name="home" msgid="3256884684164448244">"Página inicial das configurações"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> atrás"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> restante(s)"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Pequena"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 55e4def..8e05d8c 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Ativado pelo administrador"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Desativado pelo administrador"</string>
<string name="home" msgid="3256884684164448244">"Página inicial de definições"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Há <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Resta(m) <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Pequeno"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index b2ca437..d01ddb7 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Ativada pelo administrador"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Desativada pelo administrador"</string>
<string name="home" msgid="3256884684164448244">"Página inicial das configurações"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> atrás"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> restante(s)"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Pequena"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 58db725..c8587ef 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Activată de administrator"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Dezactivată de administrator"</string>
<string name="home" msgid="3256884684164448244">"Ecran principal Setări"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Acum <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Timp rămas: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Mic"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 339d2b0..5721a8d 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Включено администратором"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Отключено администратором"</string>
<string name="home" msgid="3256884684164448244">"Настройки"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> назад"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Осталось <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Мелкий"</string>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index 30e7b81..0087352 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"පරිපාලක විසින් සබල කරන ලදී"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"පරිපාලක විසින් අබල කරන ලදී"</string>
<string name="home" msgid="3256884684164448244">"සැකසීම් මුල් පිටුව"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>කට පෙර"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g>ක් ඉතිරිය"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"කුඩා"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 5ad82d6..a791a1e 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Povolené správcom"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Zakázané správcom"</string>
<string name="home" msgid="3256884684164448244">"Domovská stránka nastavení"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0 %"</item>
+ <item msgid="8934126114226089439">"50 %"</item>
+ <item msgid="1286113608943010849">"100 %"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"pred <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Zostáva <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Malé"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 4f00360..25972d0 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Omogočil skrbnik"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Onemogočil skrbnik"</string>
<string name="home" msgid="3256884684164448244">"Začetna stran nastavitev"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0 %"</item>
+ <item msgid="8934126114226089439">"50 %"</item>
+ <item msgid="1286113608943010849">"100 %"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Pred toliko časa: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Še <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Majhno"</string>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index 753d7e3..4ab5025 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Aktivizuar nga administratori"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Çaktivizuar nga administratori"</string>
<string name="home" msgid="3256884684164448244">"Kreu i cilësimeve"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> më parë"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> të mbetura"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"I vogël"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 2fee567..9858580 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Омогућио је администратор"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Онемогућио је администратор"</string>
<string name="home" msgid="3256884684164448244">"Почетна за Подешавања"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Пре <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Још <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Мали"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 60704e0..45b1b6c 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Har aktiverats av administratören"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Har inaktiverats av administratören"</string>
<string name="home" msgid="3256884684164448244">"Startskärmen för inställningar"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0 %"</item>
+ <item msgid="8934126114226089439">"50 %"</item>
+ <item msgid="1286113608943010849">"100 %"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"för <xliff:g id="ID_1">%1$s</xliff:g> sedan"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> kvar"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Små"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 245caba..2eca4a1 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Msimamizi amewasha mapendeleo ya mipangilio"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Msimamizi amezima mapendeleo ya mipangilio"</string>
<string name="home" msgid="3256884684164448244">"Ukurasa wa Kwanza wa Mipangilio"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"Zimepita <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Zimesalia <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Ndogo"</string>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index cdd95cf..bfa36c3 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"நிர்வாகி இயக்கியுள்ளார்"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"நிர்வாகி முடக்கியுள்ளார்"</string>
<string name="home" msgid="3256884684164448244">"அமைப்புகள் முகப்பு"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> முன்"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> உள்ளது"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"சிறியது"</string>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index 0c43480..4af36a6 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"నిర్వాహకులు ప్రారంభించారు"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"నిర్వాహకులు నిలిపివేసారు"</string>
<string name="home" msgid="3256884684164448244">"సెట్టింగ్ల హోమ్"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> క్రితం"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> మిగిలి ఉంది"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"చిన్నగా"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 7d2c9fb..d7fe2b6 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"เปิดใช้โดยผู้ดูแลระบบ"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"ปิดใช้โดยผู้ดูแลระบบ"</string>
<string name="home" msgid="3256884684164448244">"หน้าแรกของการตั้งค่า"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>ที่ผ่านมา"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"เหลือ <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"เล็ก"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 4c12a7d..0f8d0f0 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Na-enable ng administrator"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Na-disable ng administrator"</string>
<string name="home" msgid="3256884684164448244">"Home ng Mga Setting"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> na ang nakalipas"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> na lang"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Maliit"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index de8222b..ceb1292 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Yönetici tarafından etkinleştirildi"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Yönetici tarafından devre dışı bırakıldı"</string>
<string name="home" msgid="3256884684164448244">"Ayarlar Ana Sayfası"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"%0"</item>
+ <item msgid="8934126114226089439">"%50"</item>
+ <item msgid="1286113608943010849">"%100"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> önce"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> kaldı"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Küçük"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index e09ef59..44c9be7 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Увімкнено адміністратором"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Вимкнено адміністратором"</string>
<string name="home" msgid="3256884684164448244">"Головний екран налаштувань"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> тому"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Залишилося <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Малі елементи"</string>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index c6b6d80..6490204 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"منتظم نے فعال کر دیا"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"منتظم نے غیر فعال کر دیا"</string>
<string name="home" msgid="3256884684164448244">"ترتیبات ہوم"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> قبل"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> باقی ہیں"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"چھوٹا"</string>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index dc10339..015478f 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Administrator tomonidan yoqilgan"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Administrator tomonidan o‘chirilgan"</string>
<string name="home" msgid="3256884684164448244">"Sozlamalar"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> oldin"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> qoldi"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Kichkina"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 975aa58..e527d08 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Được bật bởi quản trị viên"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Bị tắt bởi quản trị viên"</string>
<string name="home" msgid="3256884684164448244">"Trang chủ cài đặt"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> trước"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Còn <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Nhỏ"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index b81c995..4eca743 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -324,6 +324,9 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"已被管理员启用"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"已被管理员禁用"</string>
<string name="home" msgid="3256884684164448244">"设置主屏幕"</string>
+ <!-- no translation found for battery_labels:0 (8494684293649631252) -->
+ <!-- no translation found for battery_labels:1 (8934126114226089439) -->
+ <!-- no translation found for battery_labels:2 (1286113608943010849) -->
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"还剩 <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"小"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 3388c27..c8cb2d9 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"已由管理員啟用"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"已由管理員停用"</string>
<string name="home" msgid="3256884684164448244">"主設定畫面"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"尚餘 <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"小"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 437e899..75f9758 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"已由管理員啟用"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"已由管理員停用"</string>
<string name="home" msgid="3256884684164448244">"設定主畫面"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"還剩 <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"小"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index aa8ae42..1217183 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -324,6 +324,11 @@
<string name="enabled_by_admin" msgid="2386503803463071894">"Kunikwe amandla umqondisi"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Ikhutshazwe umlawuli"</string>
<string name="home" msgid="3256884684164448244">"Ikhaya lezilungiselelo"</string>
+ <string-array name="battery_labels">
+ <item msgid="8494684293649631252">"0%"</item>
+ <item msgid="8934126114226089439">"50%"</item>
+ <item msgid="1286113608943010849">"100%"</item>
+ </string-array>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> edlule"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> osele"</string>
<string name="screen_zoom_summary_small" msgid="5867245310241621570">"Okuncane"</string>
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_focus_gain_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_focus_gain_animation.xml
similarity index 100%
rename from packages/SystemUI/res/anim/tv_pip_controls_text_focus_gain_animation.xml
rename to packages/SystemUI/res/anim/tv_pip_controls_focus_gain_animation.xml
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_focus_lose_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_focus_loss_animation.xml
similarity index 100%
rename from packages/SystemUI/res/anim/tv_pip_controls_text_focus_lose_animation.xml
rename to packages/SystemUI/res/anim/tv_pip_controls_focus_loss_animation.xml
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_lose_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_loss_animation.xml
similarity index 100%
rename from packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_lose_animation.xml
rename to packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_loss_animation.xml
diff --git a/packages/SystemUI/res/drawable/ic_hotspot_unavailable.xml b/packages/SystemUI/res/drawable/ic_hotspot_unavailable.xml
new file mode 100644
index 0000000..736cfd8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_hotspot_unavailable.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 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="root"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48"
+ android:tint="@color/qs_tile_tint_unavailable" >
+ <group
+ android:name="ic_hotspot"
+ android:translateX="23.97354"
+ android:translateY="24.26306" >
+ <group
+ android:name="ic_hotspot_pivot"
+ android:translateX="-23.21545"
+ android:translateY="-18.86649" >
+ <clip-path
+ android:name="mask"
+ android:pathData="M 38.8337860107,-40.3974914551 c 0.0,0.0 -38.4077911377,30.8523712158 -38.4077911377,30.8523712158 c 0.0,0.0 43.1884765625,43.515335083 43.1884765625,43.515335083 c 0.0,0.0 -2.4169921875,2.57838439941 -2.4169921875,2.57838439941 c 0.0,0.0 -42.9885101318,-43.0112609863 -42.9885101318,-43.0112609863 c 0.0,0.0 -32.6199798584,25.1699066162 -32.6199798584,25.1699066162 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 27.6589050293,-22.6579437256 27.6589050293,-22.6579437256 c 0.0,0.0 -30.8645172119,-34.00390625 -30.8645172119,-34.00390625 c 0.0,0.0 2.70756530762,-1.99278259277 2.70756530762,-1.99278259277 c 0.0,0.0 1.53030395508,-0.876571655273 1.53030395508,-0.876571655274 c 0.0,0.0 2.85780334473,-3.12069702148 2.85780334473,-3.12069702148 c 0.0,0.0 13.0984039307,13.025604248 13.0984039307,13.025604248 c 0.0,0.0 -3.13299560547,2.82977294922 -3.13299560547,2.82977294922 c 0.0,0.0 16.571762085,22.0471801758 16.571762085,22.0471801758 c 0.0,0.0 42.8175811768,-34.3554534912 42.8175811768,-34.3554534912 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
+ <group
+ android:name="cross" >
+ <path
+ android:name="cross_1"
+ android:pathData="M 4.44044494629,2.24310302734 c 0.0,0.0 35.4000396729,35.3999633789 35.4000396729,35.3999633789 "
+ android:strokeColor="#FFFFFFFF"
+ android:strokeAlpha="1"
+ android:strokeWidth="3.5"
+ android:fillColor="#00000000" />
+ </group>
+ <group
+ android:name="hotspot"
+ android:translateX="23.481"
+ android:translateY="18.71151" >
+ <group
+ android:name="circles"
+ android:translateX="-0.23909"
+ android:translateY="-0.10807" >
+ <path
+ android:name="circle_3"
+ android:pathData="M 0.0843505859375,-2.93901062012 c -2.30102539062,0.0 -4.16702270508,1.86602783203 -4.16702270508,4.16702270508 c 0.0,2.29898071289 1.86599731445,4.16598510742 4.16702270508,4.16598510742 c 2.29998779297,0.0 4.16598510742,-1.86700439453 4.16598510742,-4.16598510742 c 0.0,-2.30099487305 -1.86599731445,-4.16702270508 -4.16598510742,-4.16702270508 Z M 11.1185302734,5.83390808105 c 0.0,0.0 0.0009765625,0.00100708007812 0.0009765625,0.00100708007812 c 0.14501953125,-0.356994628906 0.27099609375,-0.725006103516 0.382995605469,-1.09799194336 c 0.0570068359375,-0.195007324219 0.101013183594,-0.394989013672 0.149017333984,-0.595001220703 c 0.0690002441406,-0.281005859375 0.126983642578,-0.563995361328 0.175994873047,-0.851989746094 c 0.0270080566406,-0.169006347656 0.0559997558594,-0.337005615234 0.0759887695313,-0.509002685547 c 0.0580139160156,-0.468017578125 0.0970153808594,-0.942993164062 0.0970153808593,-1.4280090332 c 0.0,0.0 0.0,-0.00100708007812 0.0,-0.00100708007812 c 0.0,-5.03900146484 -3.11099243164,-9.3450012207 -7.5119934082,-11.1229858398 c -0.00601196289062,-0.00299072265625 -0.0130004882812,-0.0050048828125 -0.0190124511719,-0.00701904296875 c -0.686004638672,-0.275970458984 -1.39999389648,-0.492980957031 -2.14099121094,-0.638977050781 c -0.072998046875,-0.0150146484375 -0.149017333984,-0.02099609375 -0.222991943359,-0.0339965820313 c -0.302001953125,-0.0540161132812 -0.605010986328,-0.106018066406 -0.916015625,-0.136016845703 c -0.389984130859,-0.0390014648438 -0.786987304688,-0.0599975585938 -1.18899536133,-0.0599975585937 c -0.402008056641,0.0 -0.799011230469,0.02099609375 -1.19000244141,0.0599975585937 c -0.304992675781,0.0299987792969 -0.602996826172,0.0809936523438 -0.901000976563,0.132995605469 c -0.0790100097656,0.0150146484375 -0.160003662109,0.02099609375 -0.238006591797,0.0370178222656 c -0.368988037109,0.0719909667969 -0.730987548828,0.164001464844 -1.08700561523,0.269989013672 c -0.00299072265625,0.00100708007812 -0.0059814453125,0.00201416015625 -0.00900268554687,0.0020141601562 c -0.351989746094,0.10498046875 -0.694000244141,0.226989746094 -1.0309753418,0.361999511719 c -0.0110168457031,0.00399780273438 -0.0220031738281,0.00698852539062 -0.0320129394531,0.0119934082031 c -4.40200805664,1.77798461914 -7.51098632812,6.083984375 -7.5119934082,11.1229858398 c 0.0,0.00799560546875 0.00198364257812,0.0160217285156 0.0019836425781,0.0240173339844 c 0.00100708007812,0.475006103516 0.0380249023438,0.940002441406 0.0950012207032,1.39898681641 c 0.02001953125,0.175994873047 0.0490112304688,0.348999023438 0.0780029296875,0.523010253906 c 0.0469970703125,0.281982421875 0.105010986328,0.557983398438 0.171997070312,0.833984375 c 0.0480041503906,0.204010009766 0.093017578125,0.410003662109 0.152008056641,0.610015869141 c 0.110992431641,0.372009277344 0.238006591797,0.736999511719 0.382019042969,1.09298706055 c 0.0,0.0 0.0009765625,0.0 0.0009765625,0.0 c 1.00701904297,2.48400878906 2.81301879883,4.56100463867 5.11001586914,5.89501953125 c 0.0,0.0 2.01599121094,-3.48300170898 2.01599121094,-3.48300170898 c -2.03900146484,-1.18402099609 -3.5119934082,-3.22500610352 -3.89898681641,-5.63900756836 c 0.0,0.0 0.0009765625,-0.00100708007812 0.0009765625,-0.00100708007812 c -0.0220031738281,-0.130981445312 -0.0369873046875,-0.265991210938 -0.052978515625,-0.399993896484 c -0.0290222167969,-0.274993896484 -0.0570068359375,-0.552001953125 -0.0570068359375,-0.834991455078 c 0.0,0.0 0.0,-0.0190124511719 0.0,-0.0190124511719 c 0.0,-3.98999023438 2.92498779297,-7.28900146484 6.74398803711,-7.89199829102 c 0.0,0.0 0.0180053710938,0.0169982910156 0.0180053710938,0.0169982910156 c 0.404998779297,-0.0639953613281 0.81298828125,-0.125 1.23599243164,-0.125 c 0.0,0.0 0.00201416015625,0.0 0.00201416015624,0.0 c 0.0,0.0 0.00299072265625,0.0 0.00299072265626,0.0 c 0.423004150391,0.0 0.830017089844,0.0610046386719 1.23501586914,0.125 c 0.0,0.0 0.0169982910156,-0.0180053710938 0.0169982910156,-0.0180053710938 c 3.81997680664,0.60400390625 6.74499511719,3.90301513672 6.74499511719,7.89199829102 c 0.0,0.292999267578 -0.0280151367188,0.578002929688 -0.0589904785156,0.861999511719 c -0.0150146484375,0.132019042969 -0.0290222167969,0.264007568359 -0.051025390625,0.393005371094 c -0.385986328125,2.41500854492 -1.85897827148,4.45599365234 -3.89797973633,5.64001464844 c 0.0,0.0 2.01599121094,3.48300170898 2.01599121094,3.48300170898 c 2.29699707031,-1.33401489258 4.10299682617,-3.41101074219 5.11001586914,-5.89602661133 Z M 19.9300231934,2.95698547363 c 0.0059814453125,-0.0659790039062 0.0159912109375,-0.130981445312 0.02099609375,-0.196990966797 c 0.031982421875,-0.462005615234 0.0479736328125,-0.928009033203 0.0489807128906,-1.39700317383 c 0,0.0 0,-0.00997924804688 0,-0.00997924804687 c 0,0.0 0,-0.00100708007812 0,-0.00100708007813 c 0,-7.22500610352 -3.84399414062,-13.5360107422 -9.58599853516,-17.0500183105 c -1.06500244141,-0.652984619141 -2.19299316406,-1.20599365234 -3.37799072266,-1.65197753906 c -0.157989501953,-0.0599975585938 -0.317016601562,-0.118011474609 -0.476989746094,-0.174011230469 c -0.317016601562,-0.110992431641 -0.634002685547,-0.218994140625 -0.9580078125,-0.31298828125 c -0.470001220703,-0.139007568359 -0.944000244141,-0.264007568359 -1.4280090332,-0.368011474609 c -0.186004638672,-0.0390014648438 -0.376983642578,-0.0669860839844 -0.565002441406,-0.101013183594 c -0.414001464844,-0.0759887695312 -0.832000732422,-0.140991210938 -1.25500488281,-0.190979003906 c -0.184997558594,-0.0220031738281 -0.369995117188,-0.0429992675781 -0.556976318359,-0.0599975585937 c -0.592010498047,-0.0530090332031 -1.18801879883,-0.0899963378906 -1.79602050781,-0.0899963378907 c -0.605987548828,0.0 -1.20300292969,0.0369873046875 -1.79598999023,0.0899963378907 c -0.186004638672,0.0169982910156 -0.371002197266,0.0379943847656 -0.555999755859,0.0599975585937 c -0.423004150391,0.0499877929688 -0.842010498047,0.114990234375 -1.25601196289,0.190979003906 c -0.18798828125,0.0350036621094 -0.377990722656,0.06201171875 -0.563995361328,0.101013183594 c -0.483001708984,0.10400390625 -0.959991455078,0.22900390625 -1.42999267578,0.368011474609 c -0.321990966797,0.093994140625 -0.638000488281,0.201995849609 -0.953002929688,0.311981201172 c -0.162994384766,0.0570068359375 -0.324005126953,0.115997314453 -0.484985351562,0.177001953125 c -1.18099975586,0.445007324219 -2.30599975586,0.997009277344 -3.36801147461,1.64700317383 c -0.00201416015625,0.00100708007812 -0.00399780273438,0.00201416015625 -0.0060119628907,0.0029907226562 c -5.74099731445,3.51400756836 -9.58499145508,9.82501220703 -9.58599853516,17.0500183105 c 0,0.0 0,0.00100708007812 0,0.00100708007813 c 0,0.0059814453125 0.00100708007812,0.0130004882812 0.0010070800781,0.0199890136719 c 0.0,0.466003417969 0.0169982910156,0.928009033203 0.0490112304688,1.38598632812 c 0.0050048828125,0.0690002441406 0.0159912109375,0.136016845703 0.02099609375,0.206024169922 c 0.031982421875,0.401000976562 0.0719909667969,0.799987792969 0.127990722656,1.19400024414 c 0.00201416015625,0.0189819335938 0.00701904296875,0.0369873046875 0.010009765625,0.0569763183594 c 0.888000488281,6.17202758789 4.59799194336,11.4250183105 9.7799987793,14.4309997559 c 0.0,0.0 2.00198364258,-3.458984375 2.00198364258,-3.458984375 c -2.58599853516,-1.5 -4.708984375,-3.70401000977 -6.11697387695,-6.34399414063 c 0.0,0.0 0.0169982910156,-0.0180053710938 0.0169982910156,-0.0180053710938 c -0.890014648438,-1.67098999023 -1.50601196289,-3.5110168457 -1.76000976562,-5.46499633789 c -0.00698852539062,-0.0500183105469 -0.010009765625,-0.102020263672 -0.0159912109375,-0.152008056641 c -0.0330200195312,-0.273010253906 -0.0610046386719,-0.545989990234 -0.0800170898437,-0.821990966797 c -0.0220031738281,-0.343017578125 -0.0350036621094,-0.68701171875 -0.0350036621094,-1.03500366211 c 0,-6.53701782227 3.92599487305,-12.1480102539 9.54299926758,-14.6310119629 c 0.157012939453,-0.0700073242188 0.313995361328,-0.135986328125 0.472015380859,-0.199981689453 c 0.373992919922,-0.151000976562 0.751983642578,-0.294006347656 1.13900756836,-0.417022705078 c 0.108978271484,-0.0350036621094 0.221984863281,-0.0619812011719 0.332000732422,-0.0950012207031 c 0.349975585938,-0.102996826172 0.705993652344,-0.194976806641 1.06597900391,-0.273986816406 c 0.114013671875,-0.0249938964844 0.227996826172,-0.052001953125 0.342010498047,-0.0750122070313 c 0.440002441406,-0.0869750976562 0.885986328125,-0.154998779297 1.33700561523,-0.203979492188 c 0.10400390625,-0.0120239257812 0.209991455078,-0.02001953125 0.315002441406,-0.0299987792969 c 0.47998046875,-0.0429992675781 0.963989257812,-0.072998046875 1.45397949219,-0.072998046875 c 0.492004394531,0.0 0.975006103516,0.0299987792969 1.45401000977,0.072998046875 c 0.105987548828,0.00997924804688 0.212005615234,0.0179748535156 0.316986083984,0.0299987792969 c 0.450012207031,0.0489807128906 0.89501953125,0.117004394531 1.33502197266,0.203002929688 c 0.115997314453,0.0239868164062 0.22998046875,0.0509948730469 0.345001220703,0.0769958496094 c 0.358001708984,0.0780029296875 0.710998535156,0.169982910156 1.06097412109,0.272003173828 c 0.111022949219,0.0329895019531 0.226013183594,0.0609741210938 0.336029052734,0.0969848632813 c 0.385986328125,0.123016357422 0.761993408203,0.265014648438 1.13497924805,0.415008544922 c 0.160003662109,0.0650024414062 0.319000244141,0.131988525391 0.477020263672,0.201995849609 c 5.61599731445,2.48400878906 9.53997802734,8.09399414062 9.53997802734,14.6310119629 c 0,0.346984863281 -0.0130004882812,0.690979003906 -0.0350036621094,1.03399658203 c -0.0179748535156,0.274993896484 -0.0469970703125,0.548004150391 -0.0789794921875,0.819000244141 c -0.00601196289062,0.052001953125 -0.010009765625,0.10498046875 -0.0160217285156,0.154998779297 c -0.252990722656,1.95498657227 -0.871002197266,3.79400634766 -1.75997924805,5.46499633789 c 0.0,0.0 0.0169982910156,0.0180053710938 0.0169982910156,0.0180053710938 c -1.40802001953,2.63998413086 -3.53100585938,4.84399414062 -6.11700439453,6.34399414063 c 0.0,0.0 2.00198364258,3.458984375 2.00198364258,3.458984375 c 5.18402099609,-3.00698852539 8.89501953125,-8.26300048828 9.78100585938,-14.4379882813 c 0.00201416015625,-0.0169982910156 0.00601196289062,-0.0320129394531 0.0079956054688,-0.0490112304688 c 0.0570068359375,-0.39697265625 0.0970153808594,-0.798980712891 0.129028320312,-1.20300292969 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/layout-television/recents_on_tv.xml b/packages/SystemUI/res/layout-television/recents_on_tv.xml
index 1dbd1b3..2b78bee 100644
--- a/packages/SystemUI/res/layout-television/recents_on_tv.xml
+++ b/packages/SystemUI/res/layout-television/recents_on_tv.xml
@@ -21,6 +21,7 @@
android:clipChildren="false"
android:clipToPadding="false"
android:background="@drawable/recents_tv_background_gradient">
+
<com.android.systemui.recents.tv.views.TaskStackHorizontalGridView
android:id="@+id/task_list"
android:layout_width="wrap_content"
@@ -32,12 +33,24 @@
android:focusable="true"
android:layoutDirection="rtl" />
- <!-- Placeholder view to give focus to the PIP menus. -->
+ <!-- Placeholder view to give focus to the PIP menus in talkback mode -->
<View
android:id="@+id/pip"
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true"
- android:visibility="visible" />
+ android:visibility="gone" />
+
+ <!-- Placeholder to dismiss during talkback. -->
+ <ImageView
+ android:id="@+id/dismiss_placeholder"
+ android:layout_width="@dimen/recents_tv_dismiss_icon_size"
+ android:layout_height="@dimen/recents_tv_dismiss_icon_size"
+ android:layout_gravity="bottom|center_horizontal"
+ android:layout_marginBottom="50dp"
+ android:src="@drawable/ic_cancel_white_24dp"
+ android:contentDescription="@string/status_bar_accessibility_dismiss_recents"
+ android:focusable="true"
+ android:visibility="gone" />
</com.android.systemui.recents.tv.views.RecentsTvView>
diff --git a/packages/SystemUI/res/layout/notification_children_divider.xml b/packages/SystemUI/res/layout/notification_children_divider.xml
index dad7cea..76315b8 100644
--- a/packages/SystemUI/res/layout/notification_children_divider.xml
+++ b/packages/SystemUI/res/layout/notification_children_divider.xml
@@ -20,4 +20,4 @@
android:id="@+id/notification_more_divider"
android:layout_width="match_parent"
android:layout_height="@dimen/notification_divider_height"
- android:background="#61000000" />
+ android:background="#FF616161" />
diff --git a/packages/SystemUI/res/layout/qs_customize_panel_content.xml b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
index 6438564..ca0248e 100644
--- a/packages/SystemUI/res/layout/qs_customize_panel_content.xml
+++ b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
@@ -35,6 +35,7 @@
android:importantForAccessibility="no" />
<View
+ android:id="@+id/nav_bar_background"
android:layout_width="match_parent"
android:layout_height="@dimen/navigation_bar_size"
android:layout_gravity="bottom"
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index 32839d8..63390e2 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -44,7 +44,7 @@
android:layout_height="wrap_content"
/>
- <ScrollView
+ <com.android.systemui.qs.NonInterceptingScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
@@ -52,7 +52,7 @@
android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
- </ScrollView>
+ </com.android.systemui.qs.NonInterceptingScrollView>
<include layout="@layout/qs_detail_buttons" />
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 658571e..2c8a559 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -53,8 +53,7 @@
android:layout_width="@dimen/notification_panel_width"
android:layout_height="match_parent"
android:layout_gravity="@integer/notification_panel_layout_gravity"
- android:layout_marginBottom="@dimen/close_handle_underlap"
- android:importantForAccessibility="no" />
+ android:layout_marginBottom="@dimen/close_handle_underlap" />
<ViewStub
android:id="@+id/keyguard_user_switcher"
diff --git a/packages/SystemUI/res/layout/tv_pip_control_button.xml b/packages/SystemUI/res/layout/tv_pip_control_button.xml
index f18a5da..096dda8 100644
--- a/packages/SystemUI/res/layout/tv_pip_control_button.xml
+++ b/packages/SystemUI/res/layout/tv_pip_control_button.xml
@@ -23,15 +23,25 @@
<ImageView android:id="@+id/button"
android:layout_width="34dp"
android:layout_height="34dp"
- android:padding="5dp"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
android:focusable="true"
- android:src="@drawable/ic_fullscreen_white_24dp"
- android:background="@drawable/tv_pip_button_focused"
- android:layerType="software" />
+ android:src="@drawable/tv_pip_button_focused"
+ android:importantForAccessibility="yes" />
+
+ <ImageView android:id="@+id/icon"
+ android:layout_width="34dp"
+ android:layout_height="34dp"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:padding="5dp"
+ android:importantForAccessibility="no" />
<TextView android:id="@+id/desc"
android:layout_width="100dp"
android:layout_height="wrap_content"
+ android:layout_below="@id/icon"
+ android:layout_centerHorizontal="true"
android:layout_marginTop="3dp"
android:gravity="center"
android:text="@string/pip_fullscreen"
diff --git a/packages/SystemUI/res/layout/tv_pip_recents_overlay.xml b/packages/SystemUI/res/layout/tv_pip_recents_overlay.xml
index 557bbe6..f157fd5 100644
--- a/packages/SystemUI/res/layout/tv_pip_recents_overlay.xml
+++ b/packages/SystemUI/res/layout/tv_pip_recents_overlay.xml
@@ -15,7 +15,7 @@
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="top|center_horizontal"
android:orientation="vertical">
@@ -33,7 +33,8 @@
android:layout_height="32dp"
android:translationY="-46dp"
android:layout_gravity="top|center_horizontal"
- android:background="@drawable/tv_pip_recents_overlay_scrim" />
+ android:background="@drawable/tv_pip_recents_overlay_scrim"
+ android:alpha="0" />
<com.android.systemui.tv.pip.PipControlsView
android:id="@+id/pip_control_contents"
android:layout_width="wrap_content"
@@ -42,6 +43,8 @@
android:layout_gravity="top|center_horizontal" />
</com.android.systemui.tv.pip.PipRecentsControlsView>
+ <!-- Placeholder view to handle focus change between Recents row and PIP controls
+ in talkback mode -->
<View
android:id="@+id/recents"
android:layout_width="1dp"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b8f576b..cbb3c0a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -248,6 +248,9 @@
<!-- The height of the divider between the individual notifications. -->
<dimen name="notification_divider_height">0.5dp</dimen>
+ <!-- The height of a notification header -->
+ <dimen name="notification_header_height">53dp</dimen>
+
<!-- The height of the divider between the individual notifications when the notification wants it to be increased. This is currently the case for notification groups -->
<dimen name="notification_divider_height_increased">6dp</dimen>
diff --git a/packages/SystemUI/res/values/values_tv.xml b/packages/SystemUI/res/values/values_tv.xml
index dc0483f..9259415 100644
--- a/packages/SystemUI/res/values/values_tv.xml
+++ b/packages/SystemUI/res/values/values_tv.xml
@@ -16,5 +16,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<item format="float" type="integer" name="unselected_scale">1.0</item>
<item format="float" type="integer" name="selected_scale">1.259</item>
- <item format="float" type="integer" name="dismiss_unselected_alpha">0.1</item>
+ <item format="float" type="integer" name="dismiss_unselected_alpha">0.3</item>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index b6d8095..7a5e322 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -45,6 +45,7 @@
void setUserLockedChild(View v, boolean userLocked);
void expansionStateChanged(boolean isExpanding);
int getMaxExpandHeight(ExpandableView view);
+ void setExpansionCancelled(View view);
}
private static final String TAG = "ExpandHelper";
@@ -558,6 +559,8 @@
public void onAnimationEnd(Animator animation) {
if (!mCancelled) {
mCallback.setUserExpandedChild(scaledView, expand);
+ } else {
+ mCallback.setExpansionCancelled(scaledView);
}
mCallback.setUserLockedChild(scaledView, false);
mScaleAnimation.removeListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/NonInterceptingScrollView.java b/packages/SystemUI/src/com/android/systemui/qs/NonInterceptingScrollView.java
new file mode 100644
index 0000000..15e1c96
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/NonInterceptingScrollView.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 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.qs;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.ScrollView;
+
+/**
+ * ScrollView that disallows intercepting for touches that can cause scrolling.
+ */
+public class NonInterceptingScrollView extends ScrollView {
+
+ private float mInitialY;
+
+ public NonInterceptingScrollView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ int action = ev.getActionMasked();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ mInitialY = ev.getY();
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ requestDisallowInterceptTouchEvent(false);
+ break;
+ default:
+ if (canScrollVertically(ev.getY() > mInitialY ? -1 : 1)) {
+ requestDisallowInterceptTouchEvent(true);
+ }
+ break;
+ }
+ return super.onTouchEvent(ev);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
index f05aa3c..feacaa0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
@@ -154,9 +154,9 @@
event.setClassName(mAccessibilityClass);
if (Switch.class.getName().equals(mAccessibilityClass)) {
String label = getResources()
- .getString(mTileState ? R.string.switch_bar_on : R.string.switch_bar_off);
+ .getString(!mTileState ? R.string.switch_bar_on : R.string.switch_bar_off);
event.setContentDescription(label);
- event.setChecked(mTileState);
+ event.setChecked(!mTileState);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 61933b4..4bf85c7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -19,6 +19,7 @@
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
+import android.content.res.Configuration;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
@@ -103,6 +104,17 @@
mRecyclerView.setItemAnimator(animator);
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ View navBackdrop = findViewById(R.id.nav_bar_background);
+ if (navBackdrop != null) {
+ boolean shouldShow = newConfig.smallestScreenWidthDp >= 600
+ || newConfig.orientation != Configuration.ORIENTATION_LANDSCAPE;
+ navBackdrop.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
+ }
+ }
+
public void setHost(QSTileHost host) {
mHost = host;
mPhoneStatusBar = host.getPhoneStatusBar();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 61a92b4..60c24d0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -286,10 +286,11 @@
private void selectPosition(int position, View v) {
// Remove the placeholder.
mAccessibilityMoving = false;
- move(mAccessibilityFromIndex, position, v);
- mTiles.remove(mEditIndex);
+ mTiles.remove(mEditIndex--);
notifyItemRemoved(mEditIndex - 1);
+ move(mAccessibilityFromIndex, position, v);
updateDividerLocations();
+ notifyDataSetChanged();
saveSpecs(mHost);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 212f179..16b1158 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -81,6 +81,8 @@
private IQSService mService;
private boolean mUnbindImmediate;
private TileChangeListener mChangeListener;
+ // Return value from bindServiceAsUser, determines whether safe to call unbind.
+ private boolean mIsBound;
public TileLifecycleManager(Handler handler, Context context, Intent intent, UserHandle user) {
mContext = context;
@@ -132,7 +134,7 @@
}
if (DEBUG) Log.d(TAG, "Binding service " + mIntent + " " + mUser);
mBindTryCount++;
- mContext.bindServiceAsUser(mIntent, this,
+ mIsBound = mContext.bindServiceAsUser(mIntent, this,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
mUser);
} else {
@@ -140,7 +142,10 @@
// Give it another chance next time it needs to be bound, out of kindness.
mBindTryCount = 0;
mWrapper = null;
- mContext.unbindService(this);
+ if (mIsBound) {
+ mContext.unbindService(this);
+ mIsBound = false;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 3587262..1c134c1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -16,15 +16,22 @@
package com.android.systemui.qs.tiles;
+import android.content.BroadcastReceiver;
+import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.os.UserManager;
import android.provider.Settings;
+import android.provider.Settings.Global;
+import android.text.SpannableStringBuilder;
+import android.text.style.ForegroundColorSpan;
import android.widget.Switch;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
+import com.android.systemui.qs.GlobalSetting;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.HotspotController;
@@ -36,12 +43,22 @@
private final AnimationIcon mDisable =
new AnimationIcon(R.drawable.ic_hotspot_disable_animation,
R.drawable.ic_hotspot_enable);
+ private final Icon mUnavailable =
+ ResourceIcon.get(R.drawable.ic_hotspot_unavailable);
private final HotspotController mController;
private final Callback mCallback = new Callback();
+ private final GlobalSetting mAirplaneMode;
+ private boolean mListening;
public HotspotTile(Host host) {
super(host);
mController = host.getHotspotController();
+ mAirplaneMode = new GlobalSetting(mContext, mHandler, Global.AIRPLANE_MODE_ON) {
+ @Override
+ protected void handleValueChanged(int value) {
+ refreshState();
+ }
+ };
}
@Override
@@ -61,11 +78,18 @@
@Override
public void setListening(boolean listening) {
+ if (mListening == listening) return;
+ mListening = listening;
if (listening) {
mController.addCallback(mCallback);
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ mContext.registerReceiver(mReceiver, filter);
} else {
mController.removeCallback(mCallback);
+ mContext.unregisterReceiver(mReceiver);
}
+ mAirplaneMode.setListening(listening);
}
@Override
@@ -76,6 +100,9 @@
@Override
protected void handleClick() {
final boolean isEnabled = (Boolean) mState.value;
+ if (!isEnabled && mAirplaneMode.getValue() != 0) {
+ return;
+ }
MetricsLogger.action(mContext, getMetricsCategory(), !isEnabled);
mController.setHotspotEnabled(!isEnabled);
}
@@ -96,6 +123,13 @@
state.value = mController.isHotspotEnabled();
}
state.icon = state.value ? mEnable : mDisable;
+ if (mAirplaneMode.getValue() != 0) {
+ final int disabledColor = mHost.getContext().getColor(R.color.qs_tile_tint_unavailable);
+ state.label = new SpannableStringBuilder().append(state.label,
+ new ForegroundColorSpan(disabledColor),
+ SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
+ state.icon = mUnavailable;
+ }
state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
= Switch.class.getName();
state.contentDescription = state.label;
@@ -121,4 +155,13 @@
refreshState(enabled);
}
};
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction())) {
+ refreshState();
+ }
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
index 1715356..bb8bfee 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
@@ -35,7 +35,7 @@
public static final boolean DisableBackgroundCache = false;
// Enables the task affiliations
public static final boolean EnableAffiliatedTaskGroups = false;
- // TODO: To be repurposed
+ // Enables the button above the stack
public static final boolean EnableStackActionButton = true;
// Overrides the Tuner flags and enables the timeout
private static final boolean EnableFastToggleTimeout = false;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index cfc6c52..b20f46f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -372,7 +372,7 @@
if (stack.getTaskCount() > 0) {
// Only preload the icon (but not the thumbnail since it may not have been taken for
// the pausing activity)
- preloadIcon(runningTask);
+ preloadIcon(runningTask.id);
// At this point, we don't know anything about the stack state. So only calculate
// the dimensions of the thumbnail that we need for the transition into Recents, but
@@ -664,10 +664,10 @@
/**
* Preloads the icon of a task.
*/
- private void preloadIcon(ActivityManager.RunningTaskInfo task) {
+ private void preloadIcon(int runningTaskId) {
// Ensure that we load the running task's icon
RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
- launchOpts.runningTaskId = task.id;
+ launchOpts.runningTaskId = runningTaskId;
launchOpts.loadThumbnails = false;
launchOpts.onlyLoadForCache = true;
Recents.getTaskLoader().loadTasks(mContext, sInstanceLoadPlan, launchOpts);
@@ -699,7 +699,7 @@
private ActivityOptions getThumbnailTransitionActivityOptions(
ActivityManager.RunningTaskInfo runningTask, TaskStackView stackView,
Rect windowOverrideRect) {
- if (runningTask.stackId == FREEFORM_WORKSPACE_STACK_ID) {
+ if (runningTask != null && runningTask.stackId == FREEFORM_WORKSPACE_STACK_ID) {
ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>();
ArrayList<Task> tasks = stackView.getStack().getStackTasks();
TaskStackLayoutAlgorithm stackLayout = stackView.getStackAlgorithm();
@@ -810,6 +810,10 @@
RecentsTaskLoader loader = Recents.getTaskLoader();
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+ int runningTaskId = !mLaunchedWhileDocking && (runningTask != null)
+ ? runningTask.id
+ : -1;
+
// In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
// should always preload the tasks now. If we are dragging in recents, reload them as
// the stacks might have changed.
@@ -818,7 +822,7 @@
sInstanceLoadPlan = loader.createLoadPlan(mContext);
}
if (mLaunchedWhileDocking || mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) {
- loader.preloadTasks(sInstanceLoadPlan, runningTask.id, !isHomeStackVisible);
+ loader.preloadTasks(sInstanceLoadPlan, runningTaskId, !isHomeStackVisible);
}
TaskStack stack = sInstanceLoadPlan.getTaskStack();
@@ -830,12 +834,12 @@
launchState.launchedFromApp = useThumbnailTransition || mLaunchedWhileDocking;
launchState.launchedViaDockGesture = mLaunchedWhileDocking;
launchState.launchedViaDragGesture = mDraggingInRecents;
- launchState.launchedToTaskId = (runningTask != null) ? runningTask.id : -1;
+ launchState.launchedToTaskId = runningTaskId;
launchState.launchedWithAltTab = mTriggeredFromAltTab;
// Preload the icon (this will be a null-op if we have preloaded the icon already in
// preloadRecents())
- preloadIcon(runningTask);
+ preloadIcon(runningTaskId);
// Update the header bar if necessary
Rect windowOverrideRect = getWindowRectOverride(growTarget);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 50e28ca..26200d0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -228,8 +228,8 @@
/**
* Notifies when a task has been removed from the stack.
*/
- void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
- Task newFrontMostTask, AnimationProps animation, boolean fromDockGesture);
+ void onStackTaskRemoved(TaskStack stack, Task removedTask, Task newFrontMostTask,
+ AnimationProps animation, boolean fromDockGesture);
/**
* Notifies when all tasks have been removed from the stack.
@@ -609,12 +609,11 @@
*/
public void removeTask(Task t, AnimationProps animation, boolean fromDockGesture) {
if (mStackTaskList.contains(t)) {
- boolean wasFrontMostTask = (getStackFrontMostTask(false /* includeFreeform */) == t);
removeTaskImpl(mStackTaskList, t);
Task newFrontMostTask = getStackFrontMostTask(false /* includeFreeform */);
if (mCb != null) {
// Notify that a task has been removed
- mCb.onStackTaskRemoved(this, t, wasFrontMostTask, newFrontMostTask, animation,
+ mCb.onStackTaskRemoved(this, t, newFrontMostTask, animation,
fromDockGesture);
}
}
@@ -648,6 +647,7 @@
ArrayMap<Task.TaskKey, Task> currentTasksMap = createTaskKeyMapFromList(mRawTaskList);
ArrayMap<Task.TaskKey, Task> newTasksMap = createTaskKeyMapFromList(tasks);
ArrayList<Task> addedTasks = new ArrayList<>();
+ ArrayList<Task> removedTasks = new ArrayList<>();
ArrayList<Task> allTasks = new ArrayList<>();
// Disable notifications if there are no callbacks
@@ -661,11 +661,7 @@
Task task = mRawTaskList.get(i);
if (!newTasksMap.containsKey(task.key)) {
if (notifyStackChanges) {
- // If we are notifying, then remove the task now, otherwise the raw task list
- // will be reset at the end of this method
- removeTask(task, AnimationProps.IMMEDIATE, false /* fromDockGesture */);
- mCb.onStackTaskRemoved(this, task, i == (taskCount - 1), null,
- AnimationProps.IMMEDIATE, false /* fromDockGesture */);
+ removedTasks.add(task);
}
}
task.setGroup(null);
@@ -699,6 +695,14 @@
// Update the affiliated groupings
createAffiliatedGroupings(context);
+ // Only callback for the removed tasks after the stack has updated
+ int removedTaskCount = removedTasks.size();
+ Task newFrontMostTask = getStackFrontMostTask(false);
+ for (int i = 0; i < removedTaskCount; i++) {
+ mCb.onStackTaskRemoved(this, removedTasks.get(i), newFrontMostTask,
+ AnimationProps.IMMEDIATE, false /* fromDockGesture */);
+ }
+
// Only callback for the newly added tasks after this stack has been updated
int addedTaskCount = addedTasks.size();
for (int i = 0; i < addedTaskCount; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
index ecb64f6..ecb12d3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
@@ -81,6 +81,7 @@
private long mLastTabKeyEventTime;
private boolean mIgnoreAltTabRelease;
private boolean mLaunchedFromHome;
+ private boolean mTalkBackEnabled;
private RecentsTvView mRecentsView;
private View mPipView;
@@ -133,15 +134,22 @@
@Override
public void onRecentsFocused() {
- mRecentsView.requestFocus();
- mRecentsView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ if (mTalkBackEnabled) {
+ mTaskStackHorizontalGridView.requestFocus();
+ mTaskStackHorizontalGridView.sendAccessibilityEvent(
+ AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ }
+ mTaskStackHorizontalGridView.startFocusGainAnimation();
}
};
+
private final View.OnFocusChangeListener mPipViewFocusChangeListener =
new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
- handlePipViewFocusChange(hasFocus);
+ if (hasFocus) {
+ requestPipControlsFocus();
+ }
}
};
@@ -194,17 +202,18 @@
loadOpts.numVisibleTaskThumbnails = numVisibleTasks;
loader.loadTasks(this, plan, loadOpts);
-
- mRecentsView.setTaskStack(stack);
List stackTasks = stack.getStackTasks();
Collections.reverse(stackTasks);
if (mTaskStackViewAdapter == null) {
mTaskStackViewAdapter = new TaskStackHorizontalViewAdapter(stackTasks);
mTaskStackHorizontalGridView = mRecentsView
.setTaskStackViewAdapter(mTaskStackViewAdapter);
+ mHomeRecentsEnterExitAnimationHolder = new HomeRecentsEnterExitAnimationHolder(
+ getApplicationContext(), mTaskStackHorizontalGridView);
} else {
mTaskStackViewAdapter.setNewStackTasks(stackTasks);
}
+ mRecentsView.init(stack);
if (launchState.launchedToTaskId != -1) {
ArrayList<Task> tasks = stack.getStackTasks();
@@ -305,6 +314,7 @@
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
mPipView = findViewById(R.id.pip);
+ mPipView.setOnFocusChangeListener(mPipViewFocusChangeListener);
// Place mPipView at the PIP bounds for fine tuned focus handling.
Rect pipBounds = mPipManager.getRecentsFocusedPipBounds();
LayoutParams lp = (LayoutParams) mPipView.getLayoutParams();
@@ -342,7 +352,6 @@
if(mLaunchedFromHome) {
mHomeRecentsEnterExitAnimationHolder.startEnterAnimation(mPipManager.isPipShown());
}
- mTaskStackViewAdapter.setResetAddedCards(true);
EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
}
@@ -353,19 +362,6 @@
// Update the recent tasks
updateRecentsTasks();
- mHomeRecentsEnterExitAnimationHolder = new HomeRecentsEnterExitAnimationHolder(
- getApplicationContext(), mTaskStackHorizontalGridView);
- if(mTaskStackHorizontalGridView != null &&
- mTaskStackHorizontalGridView.getChildCount() > 0) {
- if(mLaunchedFromHome) {
- mHomeRecentsEnterExitAnimationHolder.setEnterFromHomeStartingAnimationValues();
- } else {
- mHomeRecentsEnterExitAnimationHolder.setEnterFromAppStartingAnimationValues();
- }
- } else {
- mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
- }
-
// If this is a new instance from a configuration change, then we have to manually trigger
// the enter animation state, or if recents was relaunched by AM, without going through
// the normal mechanisms
@@ -387,15 +383,52 @@
} else {
mTaskStackHorizontalGridView.setSelectedPosition(0);
}
+ mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
- updatePipUI();
+ View dismissPlaceholder = findViewById(R.id.dismiss_placeholder);
+ mTalkBackEnabled = ssp.isTouchExplorationEnabled();
+ if (mTalkBackEnabled) {
+ dismissPlaceholder.setAccessibilityTraversalBefore(R.id.task_list);
+ dismissPlaceholder.setAccessibilityTraversalAfter(R.id.dismiss_placeholder);
+ mTaskStackHorizontalGridView.setAccessibilityTraversalAfter(R.id.dismiss_placeholder);
+ mTaskStackHorizontalGridView.setAccessibilityTraversalBefore(R.id.pip);
+ dismissPlaceholder.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mTaskStackHorizontalGridView.requestFocus();
+ mTaskStackHorizontalGridView.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ Task focusedTask = mTaskStackHorizontalGridView.getFocusedTask();
+ if (focusedTask != null) {
+ mTaskStackViewAdapter.removeTask(focusedTask);
+ EventBus.getDefault().send(new DeleteTaskDataEvent(focusedTask));
+ }
+ }
+ });
+ }
+
+ // Initialize PIP UI
+ if (mPipManager.isPipShown()) {
+ if (mTalkBackEnabled) {
+ // If talkback is on, use the mPipView to handle focus changes
+ // between recents row and PIP controls.
+ mPipView.setVisibility(View.VISIBLE);
+ } else {
+ mPipView.setVisibility(View.GONE);
+ }
+ // When PIP view has focus, recents overlay view will takes the focus
+ // as if it's the part of the Recents UI.
+ mPipRecentsOverlayManager.requestFocus(mTaskStackViewAdapter.getItemCount() > 0);
+ } else {
+ mPipView.setVisibility(View.GONE);
+ mPipRecentsOverlayManager.removePipRecentsOverlayView();
+ }
}
@Override
public void onPause() {
super.onPause();
mPipRecentsOverlayManager.onRecentsPaused();
- mTaskStackViewAdapter.setResetAddedCards(false);
}
@Override
@@ -514,6 +547,7 @@
public final void onBusEvent(AllTaskViewsDismissedEvent event) {
if (mPipManager.isPipShown()) {
mRecentsView.showEmptyView();
+ mPipRecentsOverlayManager.requestFocus(false);
} else {
dismissRecentsToHome(false);
}
@@ -527,10 +561,14 @@
@Override
public boolean onPreDraw() {
mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
- if(mLaunchedFromHome) {
- mHomeRecentsEnterExitAnimationHolder.setEnterFromHomeStartingAnimationValues();
+ // Sets the initial values for enter animation.
+ // Animation will be started in {@link #onEnterAnimationComplete()}
+ if (mLaunchedFromHome) {
+ mHomeRecentsEnterExitAnimationHolder
+ .setEnterFromHomeStartingAnimationValues(mPipManager.isPipShown());
} else {
- mHomeRecentsEnterExitAnimationHolder.setEnterFromAppStartingAnimationValues();
+ mHomeRecentsEnterExitAnimationHolder
+ .setEnterFromAppStartingAnimationValues(mPipManager.isPipShown());
}
// We post to make sure that this information is delivered after this traversals is
// finished.
@@ -544,35 +582,25 @@
}
private void updatePipUI() {
- if (mPipManager.isPipShown()) {
- mPipView.setVisibility(View.VISIBLE);
- mPipView.setOnFocusChangeListener(mPipViewFocusChangeListener);
- if (mPipView.hasFocus()) {
- // This can happen only if the activity is resumed. Ask for reset.
- handlePipViewFocusChange(true);
- } else {
- mPipView.requestFocus();
- }
- } else {
- mPipView.setVisibility(View.GONE);
+ if (!mPipManager.isPipShown()) {
mPipRecentsOverlayManager.removePipRecentsOverlayView();
+ mTaskStackHorizontalGridView.startFocusLossAnimation();
+ } else {
+ Log.w(TAG, "An activity entered PIP mode while Recents is shown");
}
}
/**
- * Handles the PIP view's focus change.
+ * Requests the focus to the PIP controls.
* This starts the relevant recents row animation
* and give focus to the recents overlay if needed.
*/
- private void handlePipViewFocusChange(boolean hasFocus) {
- mRecentsView.startRecentsRowFocusAnimation(!hasFocus);
- if (hasFocus) {
- // When PIP view has focus, recents overlay view will takes the focus
- // as if it's the part of the Recents UI.
- mPipRecentsOverlayManager.requestFocus(
- mTaskStackViewAdapter.getItemCount() > 0);
- } else {
- mPipRecentsOverlayManager.clearFocus();
+ public void requestPipControlsFocus() {
+ if (!mPipManager.isPipShown()) {
+ return;
}
+
+ mTaskStackHorizontalGridView.startFocusLossAnimation();
+ mPipRecentsOverlayManager.requestFocus(mTaskStackViewAdapter.getItemCount() > 0);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java
index 92718a3..9faaa4b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java
@@ -74,19 +74,35 @@
}
}
- public void setEnterFromHomeStartingAnimationValues() {
+ /**
+ * Sets the initial values Recents enter animation
+ * when Recents is started from the Launcher.
+ */
+ public void setEnterFromHomeStartingAnimationValues(boolean isPipShown) {
for(int i = 0; i < mGridView.getChildCount(); i++) {
TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
view.setTranslationX(0);
view.setAlpha(0.0f);
+ view.getInfoFieldView().setAlpha(isPipShown ? 0 : 1f);
+ if (isPipShown && view.hasFocus()) {
+ view.getViewFocusAnimator().changeSize(false);
+ }
}
}
- public void setEnterFromAppStartingAnimationValues() {
+ /**
+ * Sets the initial values Recents enter animation
+ * when Recents is started from an app.
+ */
+ public void setEnterFromAppStartingAnimationValues(boolean isPipShown) {
for(int i = 0; i < mGridView.getChildCount(); i++) {
TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
view.setTranslationX(0);
- view.setAlpha(1.0f);
+ view.setAlpha(isPipShown ? mDimAlpha : 1f);
+ view.getInfoFieldView().setAlpha(isPipShown ? 0 : 1f);
+ if (isPipShown && view.hasFocus()) {
+ view.getViewFocusAnimator().changeSize(false);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
index 45c1537..8a4cf399 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
@@ -29,11 +29,11 @@
* Recents row's focus animation with PIP controls.
*/
public class RecentsRowFocusAnimationHolder {
- private View mView;
- private View mTitleView;
+ private final View mView;
+ private final View mTitleView;
private AnimatorSet mFocusGainAnimatorSet;
- private AnimatorSet mFocusLoseAnimatorSet;
+ private AnimatorSet mFocusLossAnimatorSet;
public RecentsRowFocusAnimationHolder(View view, View titleView) {
mView = view;
@@ -50,28 +50,45 @@
mFocusGainAnimatorSet.setDuration(duration);
mFocusGainAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- mFocusLoseAnimatorSet = new AnimatorSet();
- mFocusLoseAnimatorSet.playTogether(
+ mFocusLossAnimatorSet = new AnimatorSet();
+ mFocusLossAnimatorSet.playTogether(
// Animation doesn't start from the current value (1f) sometimes,
// so specify the desired initial value here.
ObjectAnimator.ofFloat(mView, "alpha", 1f, dimAlpha),
ObjectAnimator.ofFloat(mTitleView, "alpha", 0f));
- mFocusLoseAnimatorSet.setDuration(duration);
- mFocusLoseAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ mFocusLossAnimatorSet.setDuration(duration);
+ mFocusLossAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
}
/**
- * Returns the Recents row's focus change animation.
+ * Starts the Recents row's focus gain animation.
*/
- public Animator getFocusChangeAnimator(boolean hasFocus) {
- return hasFocus ? mFocusGainAnimatorSet : mFocusLoseAnimatorSet;
+ public void startFocusGainAnimation() {
+ cancelAnimator(mFocusLossAnimatorSet);
+ mFocusGainAnimatorSet.start();
}
/**
- * Resets the views to the initial state immediately.
+ * Starts the Recents row's focus loss animation.
+ */
+ public void startFocusLossAnimation() {
+ cancelAnimator(mFocusGainAnimatorSet);
+ mFocusLossAnimatorSet.start();
+ }
+
+ /**
+ * Resets the views immediately and ends the animations.
*/
public void reset() {
+ cancelAnimator(mFocusLossAnimatorSet);
+ cancelAnimator(mFocusGainAnimatorSet);
mView.setAlpha(1f);
mTitleView.setAlpha(1f);
}
+
+ private static void cancelAnimator(Animator animator) {
+ if (animator.isStarted()) {
+ animator.cancel();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
index c3efe64..72fd7a4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
@@ -89,7 +89,7 @@
});
}
- public void setFocusProgress(float level) {
+ private void setFocusProgress(float level) {
mFocusProgress = level;
float scale = mUnselectedScale + (level * mSelectedScaleDelta);
@@ -104,35 +104,22 @@
mTargetView.getDismissIconView().setAlpha(mDismissIconAlpha * level);
mTargetView.getThumbnailView().setZ(z);
+ mTargetView.getDismissIconView().setZ(z);
}
- public float getFocusProgress() {
- return mFocusProgress;
- }
-
- public void animateFocus(boolean focused) {
+ private void animateFocus(boolean focused) {
if (mFocusAnimation.isStarted()) {
mFocusAnimation.cancel();
}
float target = focused ? 1.0f : 0.0f;
- if (getFocusProgress() != target) {
- mFocusAnimation.setFloatValues(getFocusProgress(), target);
+ if (mFocusProgress != target) {
+ mFocusAnimation.setFloatValues(mFocusProgress, target);
mFocusAnimation.start();
}
}
- public void setFocusImmediate(boolean focused) {
- if (mFocusAnimation.isStarted()) {
- mFocusAnimation.cancel();
- }
-
- float target = focused ? 1.0f : 0.0f;
-
- setFocusProgress(target);
- }
-
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (v != mTargetView) {
@@ -141,21 +128,27 @@
changeSize(hasFocus);
}
- protected void changeSize(boolean hasFocus) {
+ /**
+ * Changes the size of the {@link TaskCardView} to show its focused state.
+ */
+ public void changeSize(boolean hasFocus) {
ViewGroup.LayoutParams lp = mTargetView.getLayoutParams();
int width = lp.width;
int height = lp.height;
if (width < 0 && height < 0) {
mTargetView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
- height = mTargetView.getMeasuredHeight();
}
if (mTargetView.isAttachedToWindow() && mTargetView.hasWindowFocus() &&
mTargetView.getVisibility() == View.VISIBLE) {
animateFocus(hasFocus);
} else {
- setFocusImmediate(hasFocus);
+ // Set focus immediately.
+ if (mFocusAnimation.isStarted()) {
+ mFocusAnimation.cancel();
+ }
+ setFocusProgress(hasFocus ? 1.0f : 0.0f);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
index b082658..318b7f9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
@@ -54,11 +54,12 @@
private TaskStack mStack;
private TaskStackHorizontalGridView mTaskStackHorizontalView;
private View mEmptyView;
+ private View mDismissPlaceholder;
private RecentsRowFocusAnimationHolder mEmptyViewFocusAnimationHolder;
private boolean mAwaitingFirstLayout = true;
private Rect mSystemInsets = new Rect();
private RecentsTvTransitionHelper mTransitionHelper;
- private Handler mHandler;
+ private final Handler mHandler = new Handler();
private OnScrollListener mScrollListener;
public RecentsTvView(Context context) {
this(context, null);
@@ -80,24 +81,26 @@
LayoutInflater inflater = LayoutInflater.from(context);
mEmptyView = inflater.inflate(R.layout.recents_tv_empty, this, false);
addView(mEmptyView);
- mEmptyViewFocusAnimationHolder = new RecentsRowFocusAnimationHolder(mEmptyView, null);
- mHandler = new Handler();
mTransitionHelper = new RecentsTvTransitionHelper(mContext, mHandler);
}
- public void setTaskStack(TaskStack stack) {
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mDismissPlaceholder = findViewById(R.id.dismiss_placeholder);
+ mTaskStackHorizontalView = (TaskStackHorizontalGridView) findViewById(R.id.task_list);
+ }
+
+ /**
+ * Initialize the view.
+ */
+ public void init(TaskStack stack) {
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
mStack = stack;
- if (mTaskStackHorizontalView != null) {
- mTaskStackHorizontalView.reset();
- mTaskStackHorizontalView.setStack(stack);
- } else {
- mTaskStackHorizontalView = (TaskStackHorizontalGridView) findViewById(R.id.task_list);
- mTaskStackHorizontalView.setStack(stack);
- }
+ mTaskStackHorizontalView.init(stack);
if (stack.getStackTaskCount() > 0) {
hideEmptyView();
@@ -105,6 +108,7 @@
showEmptyView();
}
+ // Layout with the new stack
requestLayout();
}
@@ -182,22 +186,14 @@
}
/**
- * Starts the focus change animation.
- */
- public void startRecentsRowFocusAnimation(boolean hasFocus) {
- if (mEmptyView.getVisibility() == View.VISIBLE) {
- mEmptyViewFocusAnimationHolder.getFocusChangeAnimator(hasFocus).start();
- } else {
- mTaskStackHorizontalView.startRecentsRowFocusAnimation(hasFocus);
- }
- }
-
- /**
* Hides the task stack and shows the empty view.
*/
public void showEmptyView() {
mEmptyView.setVisibility(View.VISIBLE);
mTaskStackHorizontalView.setVisibility(View.GONE);
+ if (Recents.getSystemServices().isTouchExplorationEnabled()) {
+ mDismissPlaceholder.setVisibility(View.GONE);
+ }
}
/**
@@ -206,6 +202,9 @@
public void hideEmptyView() {
mEmptyView.setVisibility(View.GONE);
mTaskStackHorizontalView.setVisibility(View.VISIBLE);
+ if (Recents.getSystemServices().isTouchExplorationEnabled()) {
+ mDismissPlaceholder.setVisibility(View.VISIBLE);
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
index 2eede99..72a589f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
@@ -38,16 +38,20 @@
import android.widget.TextView;
import com.android.systemui.R;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.tv.RecentsTvActivity;
import com.android.systemui.recents.tv.animations.DismissAnimationsHolder;
import com.android.systemui.recents.tv.animations.RecentsRowFocusAnimationHolder;
import com.android.systemui.recents.tv.animations.ViewFocusAnimator;
-import com.android.systemui.recents.model.Task;
public class TaskCardView extends LinearLayout {
private static final String TAG = "TaskCardView";
private View mThumbnailView;
private View mDismissIconView;
+ private View mInfoFieldView;
private TextView mTitleTextView;
private ImageView mBadgeView;
private Task mTask;
@@ -77,14 +81,20 @@
protected void onFinishInflate() {
super.onFinishInflate();
mThumbnailView = findViewById(R.id.card_view_thumbnail);
+ mInfoFieldView = findViewById(R.id.card_info_field);
mTitleTextView = (TextView) findViewById(R.id.card_title_text);
mBadgeView = (ImageView) findViewById(R.id.card_extra_badge);
mDismissIconView = findViewById(R.id.dismiss_icon);
mDismissAnimationsHolder = new DismissAnimationsHolder(this);
- View title = findViewById(R.id.card_info_field);
mCornerRadius = getResources().getDimensionPixelSize(
R.dimen.recents_task_view_rounded_corners_radius);
- mRecentsRowFocusAnimationHolder = new RecentsRowFocusAnimationHolder(this, title);
+ mRecentsRowFocusAnimationHolder = new RecentsRowFocusAnimationHolder(this, mInfoFieldView);
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ if (!ssp.isTouchExplorationEnabled()) {
+ mDismissIconView.setVisibility(VISIBLE);
+ } else {
+ mDismissIconView.setVisibility(GONE);
+ }
mViewFocusAnimator = new ViewFocusAnimator(this);
}
@@ -93,6 +103,10 @@
mTitleTextView.setText(task.title);
mBadgeView.setImageDrawable(task.icon);
setThumbnailView();
+ setContentDescription(task.titleDescription);
+ mDismissState = false;
+ mDismissAnimationsHolder.reset();
+ mRecentsRowFocusAnimationHolder.reset();
}
public Task getTask() {
@@ -187,40 +201,37 @@
}
@Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- switch (keyCode) {
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ // Override dispatchKeyEvent() instead of onKeyDown() to prevent warning from ViewRootImpl.
+ switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_DPAD_DOWN : {
- if (!isInDismissState()) {
+ if (!isInDismissState() && event.getAction() == KeyEvent.ACTION_DOWN) {
setDismissState(true);
return true;
}
break;
}
case KeyEvent.KEYCODE_DPAD_UP : {
- if (isInDismissState()) {
- setDismissState(false);
- return true;
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ if (isInDismissState()) {
+ setDismissState(false);
+ } else {
+ ((RecentsTvActivity) getContext()).requestPipControlsFocus();
+ }
}
- break;
+ return true;
}
- //Eat right and left key presses when we are in dismiss state
- case KeyEvent.KEYCODE_DPAD_LEFT : {
- if (isInDismissState()) {
- return true;
- }
- break;
- }
+ // Eat right and left key presses when we are in dismiss state
+ case KeyEvent.KEYCODE_DPAD_LEFT :
case KeyEvent.KEYCODE_DPAD_RIGHT : {
if (isInDismissState()) {
return true;
}
break;
}
- default:
- break;
}
- return super.onKeyDown(keyCode, event);
+ return super.dispatchKeyEvent(event);
}
private void setDismissState(boolean dismissState) {
@@ -243,22 +254,14 @@
mDismissAnimationsHolder.startDismissAnimation(listener);
}
+ public ViewFocusAnimator getViewFocusAnimator() {
+ return mViewFocusAnimator;
+ }
+
public RecentsRowFocusAnimationHolder getRecentsRowFocusAnimationHolder() {
return mRecentsRowFocusAnimationHolder;
}
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- setDismissState(false);
- }
-
- public void reset() {
- mDismissState = false;
- mRecentsRowFocusAnimationHolder.reset();
- mDismissAnimationsHolder.reset();
- }
-
private void setThumbnailView() {
ImageView screenshotView = (ImageView) findViewById(R.id.card_view_banner_icon);
PackageManager pm = getContext().getPackageManager();
@@ -323,6 +326,10 @@
return mThumbnailView;
}
+ public View getInfoFieldView() {
+ return mInfoFieldView;
+ }
+
public View getDismissIconView() {
return mDismissIconView;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
index 9f52abd..f9b8700 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
@@ -18,8 +18,6 @@
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.content.Context;
-import android.os.Handler;
-import android.os.Message;
import android.support.v17.leanback.widget.HorizontalGridView;
import android.util.AttributeSet;
import android.view.View;
@@ -39,14 +37,6 @@
public class TaskStackHorizontalGridView extends HorizontalGridView implements TaskStackCallbacks {
private static final int ANIMATION_DELAY_MS = 50;
private static final int MSG_START_RECENT_ROW_FOCUS_ANIMATION = 100;
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == MSG_START_RECENT_ROW_FOCUS_ANIMATION) {
- startRecentsRowFocusAnimation(msg.arg1 == 1);
- }
- }
- };
private TaskStack mStack;
private Task mFocusedTask;
private AnimatorSet mRecentsRowFocusAnimation;
@@ -74,38 +64,15 @@
}
/**
- * Resets this view for reuse.
- */
- public void reset() {
- for (int i = 0; i < getChildCount(); i++) {
- ((TaskCardView) getChildAt(i)).getRecentsRowFocusAnimationHolder().reset();
- }
- if (mRecentsRowFocusAnimation != null && mRecentsRowFocusAnimation.isStarted()) {
- mRecentsRowFocusAnimation.cancel();
- }
- mHandler.removeCallbacksAndMessages(null);
- requestLayout();
- }
-
- /**
- * @param task - Task to reset
- */
- private void resetFocusedTask(Task task) {
- mFocusedTask = null;
- }
-
- /**
- * Sets the task stack.
+ * Initializes the grid view.
* @param stack
*/
- public void setStack(TaskStack stack) {
- //Set new stack
+ public void init(TaskStack stack) {
+ // Set new stack
mStack = stack;
if (mStack != null) {
mStack.setCallbacks(this);
}
- //Layout with new stack
- requestLayout();
}
/**
@@ -126,13 +93,6 @@
}
/**
- * @return - The focused task card view.
- */
- public TaskCardView getFocusedTaskCardView() {
- return ((TaskCardView)findFocus());
- }
-
- /**
* @param task
* @return Child view for given task
*/
@@ -146,32 +106,31 @@
return null;
}
+
/**
- * Starts the focus change animation.
+ * Starts the Recents row's focus gain animation.
*/
- public void startRecentsRowFocusAnimation(final boolean hasFocus) {
- if (getChildCount() == 0) {
- // Animation request may happen before view is attached.
- // Post again with small dealy so animation can be run again later.
- if (getAdapter().getItemCount() > 0) {
- mHandler.sendMessageDelayed(mHandler.obtainMessage(
- MSG_START_RECENT_ROW_FOCUS_ANIMATION, hasFocus ? 1 : 0),
- ANIMATION_DELAY_MS);
+ public void startFocusGainAnimation() {
+ for (int i = 0; i < getChildCount(); i++) {
+ TaskCardView v = (TaskCardView) getChildAt(i);
+ if (v.hasFocus()) {
+ v.getViewFocusAnimator().changeSize(true);
}
- return;
+ v.getRecentsRowFocusAnimationHolder().startFocusGainAnimation();
}
- if (mRecentsRowFocusAnimation != null && mRecentsRowFocusAnimation.isStarted()) {
- mRecentsRowFocusAnimation.cancel();
+ }
+
+ /**
+ * Starts the Recents row's focus loss animation.
+ */
+ public void startFocusLossAnimation() {
+ for (int i = 0; i < getChildCount(); i++) {
+ TaskCardView v = (TaskCardView) getChildAt(i);
+ if (v.hasFocus()) {
+ v.getViewFocusAnimator().changeSize(false);
+ }
+ v.getRecentsRowFocusAnimationHolder().startFocusLossAnimation();
}
- Animator animator = ((TaskCardView) getChildAt(0)).getRecentsRowFocusAnimationHolder()
- .getFocusChangeAnimator(hasFocus);
- mRecentsRowFocusAnimation = new AnimatorSet();
- AnimatorSet.Builder builder = mRecentsRowFocusAnimation.play(animator);
- for (int i = 1; i < getChildCount(); i++) {
- builder.with(((TaskCardView) getChildAt(i)).getRecentsRowFocusAnimationHolder()
- .getFocusChangeAnimator(hasFocus));
- }
- mRecentsRowFocusAnimation.start();
}
@Override
@@ -181,11 +140,11 @@
}
@Override
- public void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
- Task newFrontMostTask, AnimationProps animation, boolean fromDockGesture) {
+ public void onStackTaskRemoved(TaskStack stack, Task removedTask, Task newFrontMostTask,
+ AnimationProps animation, boolean fromDockGesture) {
((TaskStackHorizontalViewAdapter) getAdapter()).removeTask(removedTask);
if (mFocusedTask == removedTask) {
- resetFocusedTask(removedTask);
+ mFocusedTask = null;
}
// If there are no remaining tasks, then just close recents
if (mStack.getStackTaskCount() == 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
index b6b86b4..236d077 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
@@ -43,17 +43,13 @@
private static final String TAG = "TaskStackViewAdapter";
private List<Task> mTaskList;
private TaskStackHorizontalGridView mGridView;
- private boolean mResetAddedCards;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private TaskCardView mTaskCardView;
private Task mTask;
- private boolean mShouldReset;
public ViewHolder(View v) {
super(v);
- if(v instanceof TaskCardView) {
- mTaskCardView = (TaskCardView) v;
- }
+ mTaskCardView = (TaskCardView) v;
}
public void init(Task task) {
@@ -90,7 +86,6 @@
public void onAnimationEnd(Animator animation) {
removeTask(task);
EventBus.getDefault().send(new DeleteTaskDataEvent(task));
- mShouldReset = true;
}
@Override
@@ -131,23 +126,6 @@
}
@Override
- public void onViewAttachedToWindow(ViewHolder holder) {
- if (mResetAddedCards) {
- holder.mTaskCardView.reset();
- }
- }
-
- @Override
- public void onViewDetachedFromWindow(ViewHolder holder) {
- // We only want to reset on view detach if this is the last task being dismissed.
- // This is so that we do not reset when shifting to apps etc, as it is not needed.
- if (holder.mShouldReset) {
- holder.mTaskCardView.reset();
- holder.mShouldReset = false;
- }
- }
-
- @Override
public int getItemCount() {
return mTaskList.size();
}
@@ -178,8 +156,4 @@
mTaskList.add(position, task);
notifyItemInserted(position);
}
-
- public void setResetAddedCards(boolean reset) {
- mResetAddedCards = reset;
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index f4c13d7..493e618 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -148,10 +148,12 @@
for (int i = taskViews.size() - 1; i >= 0; i--) {
TaskView tv = taskViews.get(i);
Task task = tv.getTask();
- boolean currentTaskOccludesLaunchTarget = (launchTargetTask != null &&
- launchTargetTask.group.isTaskAboveTask(task, launchTargetTask));
- boolean hideTask = (launchTargetTask != null &&
- launchTargetTask.isFreeformTask() && task.isFreeformTask());
+ boolean currentTaskOccludesLaunchTarget = launchTargetTask != null &&
+ launchTargetTask.group != null &&
+ launchTargetTask.group.isTaskAboveTask(task, launchTargetTask);
+ boolean hideTask = launchTargetTask != null &&
+ launchTargetTask.isFreeformTask() &&
+ task.isFreeformTask();
// Get the current transform for the task, which will be used to position it offscreen
stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
@@ -221,11 +223,9 @@
int taskIndexFromBack = i;
final TaskView tv = taskViews.get(i);
Task task = tv.getTask();
- boolean currentTaskOccludesLaunchTarget = false;
- if (launchTargetTask != null) {
- currentTaskOccludesLaunchTarget = launchTargetTask.group.isTaskAboveTask(task,
- launchTargetTask);
- }
+ boolean currentTaskOccludesLaunchTarget = launchTargetTask != null &&
+ launchTargetTask.group != null &&
+ launchTargetTask.group.isTaskAboveTask(task, launchTargetTask);
// Get the current transform for the task, which will be updated to the final transform
// to animate to depending on how recents was invoked
@@ -358,8 +358,9 @@
for (int i = 0; i < taskViewCount; i++) {
TaskView tv = taskViews.get(i);
Task task = tv.getTask();
- boolean currentTaskOccludesLaunchTarget = (launchingTask != null &&
- launchingTask.group.isTaskAboveTask(task, launchingTask));
+ boolean currentTaskOccludesLaunchTarget = launchingTask != null &&
+ launchingTask.group != null &&
+ launchingTask.group.isTaskAboveTask(task, launchingTask);
if (tv == launchingTaskView) {
tv.setClipViewInStack(false);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 1a197b6..0d9f77c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -1400,8 +1400,8 @@
* We expect that the {@link TaskView} associated with the removed task is already hidden.
*/
@Override
- public void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
- Task newFrontMostTask, AnimationProps animation, boolean fromDockGesture) {
+ public void onStackTaskRemoved(TaskStack stack, Task removedTask, Task newFrontMostTask,
+ AnimationProps animation, boolean fromDockGesture) {
if (mFocusedTask == removedTask) {
resetFocusedTask(removedTask);
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index e89c136..a0bae20 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -39,6 +39,7 @@
public class Divider extends SystemUI {
private DividerWindowManager mWindowManager;
private DividerView mView;
+ private final DividerState mDividerState = new DividerState();
private DockDividerVisibilityListener mDockDividerVisibilityListener;
private boolean mVisible = false;
private boolean mMinimized = false;
@@ -76,7 +77,7 @@
final int width = landscape ? size : MATCH_PARENT;
final int height = landscape ? MATCH_PARENT : size;
mWindowManager.add(mView, width, height);
- mView.setWindowManager(mWindowManager);
+ mView.injectDependencies(mWindowManager, mDividerState);
}
private void removeDivider() {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java
new file mode 100644
index 0000000..353a974
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 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.stackdivider;
+
+/**
+ * Class to hold state of divider that needs to persist across configuration changes.
+ */
+public class DividerState {
+ public boolean animateAfterRecentsDrawn;
+ public boolean growAfterRecentsDrawn;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index f728aa4..d09587b 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -30,12 +30,12 @@
import android.graphics.Region.Op;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
+import android.os.Handler;
import android.util.AttributeSet;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
-import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.VelocityTracker;
@@ -141,8 +141,6 @@
private DividerSnapAlgorithm mSnapAlgorithm;
private final Rect mStableInsets = new Rect();
- private boolean mAnimateAfterRecentsDrawn;
- private boolean mGrowAfterRecentsDrawn;
private boolean mGrowRecents;
private ValueAnimator mCurrentAnimator;
private boolean mEntranceAnimationRunning;
@@ -151,6 +149,8 @@
private GestureDetector mGestureDetector;
private boolean mDockedStackMinimized;
private boolean mAdjustedForIme;
+ private DividerState mState;
+ private final Handler mHandler = new Handler();
private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
@Override
@@ -335,8 +335,9 @@
}
}
- public void setWindowManager(DividerWindowManager windowManager) {
+ public void injectDependencies(DividerWindowManager windowManager, DividerState dividerState) {
mWindowManager = windowManager;
+ mState = dividerState;
}
public WindowManagerProxy getWindowManagerProxy() {
@@ -558,7 +559,7 @@
if (endDelay == 0 || mCancelled) {
endAction.run();
} else {
- postDelayed(endAction, endDelay);
+ mHandler.postDelayed(endAction, endDelay);
}
}
});
@@ -1048,15 +1049,15 @@
public final void onBusEvent(RecentsActivityStartingEvent recentsActivityStartingEvent) {
if (mGrowRecents && getWindowManagerProxy().getDockSide() == WindowManager.DOCKED_TOP
&& getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position) {
- mGrowAfterRecentsDrawn = true;
+ mState.growAfterRecentsDrawn = true;
startDragging(false /* animate */, false /* touching */);
}
}
public final void onBusEvent(DockedTopTaskEvent event) {
if (event.dragMode == NavigationBarGestureHelper.DRAG_MODE_NONE) {
- mGrowAfterRecentsDrawn = false;
- mAnimateAfterRecentsDrawn = true;
+ mState.growAfterRecentsDrawn = false;
+ mState.animateAfterRecentsDrawn = true;
startDragging(false /* animate */, false /* touching */);
}
updateDockSide();
@@ -1068,11 +1069,11 @@
}
public final void onBusEvent(RecentsDrawnEvent drawnEvent) {
- if (mAnimateAfterRecentsDrawn) {
- mAnimateAfterRecentsDrawn = false;
+ if (mState.animateAfterRecentsDrawn) {
+ mState.animateAfterRecentsDrawn = false;
updateDockSide();
- post(() -> {
+ mHandler.post(() -> {
// Delay switching resizing mode because this might cause jank in recents animation
// that's longer than this animation.
stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(),
@@ -1080,8 +1081,8 @@
200 /* endDelay */);
});
}
- if (mGrowAfterRecentsDrawn) {
- mGrowAfterRecentsDrawn = false;
+ if (mState.growAfterRecentsDrawn) {
+ mState.growAfterRecentsDrawn = false;
updateDockSide();
EventBus.getDefault().send(new RecentsGrowingEvent());
stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(), 336,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index e66dc74..91889d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -189,6 +189,7 @@
protected boolean mVisible;
protected ArraySet<Entry> mHeadsUpEntriesToRemoveOnSwitch = new ArraySet<>();
+ protected ArraySet<Entry> mRemoteInputEntriesToRemoveOnCollapse = new ArraySet<>();
/**
* Notifications with keys in this set are not actually around anymore. We kept them around
@@ -968,7 +969,7 @@
return vetoButton;
}
- private void performRemoveNotification(StatusBarNotification n, boolean removeView) {
+ protected void performRemoveNotification(StatusBarNotification n, boolean removeView) {
final String pkg = n.getPackageName();
final String tag = n.getTag();
final int id = n.getId();
@@ -980,6 +981,9 @@
mKeysKeptForRemoteInput.remove(n.getKey());
removeView = true;
}
+ if (mRemoteInputEntriesToRemoveOnCollapse.remove(mNotificationData.get(n.getKey()))) {
+ removeView = true;
+ }
if (removeView) {
removeNotification(n.getKey(), null);
}
@@ -1883,10 +1887,13 @@
public boolean onDismiss() {
if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(notificationKey)) {
// Release the HUN notification to the shade.
+
+ if (isPanelFullyCollapsed()) {
+ HeadsUpManager.setIsClickedNotification(row, true);
+ }
//
// In most cases, when FLAG_AUTO_CANCEL is set, the notification will
// become canceled shortly by NoMan, but we can't assume that.
- HeadsUpManager.setIsClickedNotification(row, true);
mHeadsUpManager.releaseImmediately(notificationKey);
}
StatusBarNotification parentToCancel = null;
@@ -2085,8 +2092,7 @@
/**
* The LEDs are turned off when the notification panel is shown, even just a little bit.
- * See also NotificationStackScrollLayout.setIsExpanded() for another place where we
- * attempt to do this.
+ * See also PhoneStatusBar.setPanelExpanded for another place where we attempt to do this.
*/
protected void handleVisibleToUserChanged(boolean visibleToUser) {
try {
@@ -2326,8 +2332,9 @@
Entry entry = mNotificationData.get(key);
if (entry == null) {
return;
- } else if (mHeadsUpEntriesToRemoveOnSwitch.contains(entry)) {
+ } else {
mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
+ mRemoteInputEntriesToRemoveOnCollapse.remove(entry);
}
Notification n = notification.getNotification();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index b4ce9cd..88c1503 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -22,7 +22,6 @@
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.app.Notification;
import android.content.Context;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.AnimationDrawable;
@@ -31,6 +30,8 @@
import android.os.Build;
import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
+import android.util.FloatProperty;
+import android.util.Property;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.NotificationHeaderView;
@@ -39,13 +40,14 @@
import android.view.accessibility.AccessibilityEvent;
import android.widget.Chronometer;
import android.widget.ImageView;
-import android.widget.RemoteViews;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.statusbar.notification.HybridNotificationView;
-import com.android.systemui.statusbar.notification.NotificationViewWrapper;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.stack.NotificationChildrenContainer;
@@ -65,6 +67,7 @@
private int mMaxHeadsUpHeight;
private int mNotificationMinHeight;
private int mNotificationMaxHeight;
+ private int mIncreasedPaddingBetweenElements;
/** Does this row contain layouts that can adapt to row expansion */
private boolean mExpandable;
@@ -97,7 +100,7 @@
*/
private boolean mOnKeyguard;
- private AnimatorSet mTranslateAnim;
+ private Animator mTranslateAnim;
private ArrayList<View> mTranslateableViews;
private NotificationContentView mPublicLayout;
private NotificationContentView mPrivateLayout;
@@ -115,8 +118,6 @@
private String mAppName;
private boolean mIsHeadsUp;
private boolean mLastChronometerRunning = true;
- private NotificationHeaderView mNotificationHeader;
- private NotificationViewWrapper mNotificationHeaderWrapper;
private ViewStub mChildrenContainerStub;
private NotificationGroupManager mGroupManager;
private boolean mChildrenExpanded;
@@ -128,20 +129,26 @@
private boolean mIsPinned;
private FalsingManager mFalsingManager;
private HeadsUpManager mHeadsUpManager;
- private NotificationHeaderUtil mHeaderUtil = new NotificationHeaderUtil(this);
private boolean mJustClicked;
private boolean mIconAnimationRunning;
private boolean mShowNoBackground;
private ExpandableNotificationRow mNotificationParent;
private OnExpandClickListener mOnExpandClickListener;
+ private boolean mGroupExpansionChanging;
+
private OnClickListener mExpandClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
if (!mShowingPublic && mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
- mGroupManager.toggleGroupExpansion(mStatusBarNotification);
- mOnExpandClickListener.onExpandClicked(mEntry,
- mGroupManager.isGroupExpanded(mStatusBarNotification));
+ final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
+ boolean nowExpanded = mGroupManager.toggleGroupExpansion(mStatusBarNotification);
+ mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
+ mGroupExpansionChanging = true;
+ updateBackgroundForGroupState();
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER,
+ nowExpanded);
+ logExpansionEvent(true /* userAction */, wasExpanded);
} else {
boolean nowExpanded;
if (isPinned()) {
@@ -153,6 +160,8 @@
}
notifyHeightChanged(true);
mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_EXPANDER,
+ nowExpanded);
}
}
};
@@ -160,6 +169,29 @@
private boolean mDismissed;
private boolean mKeepInParent;
private boolean mRemoved;
+ private static final Property<ExpandableNotificationRow, Float> TRANSLATE_CONTENT =
+ new FloatProperty<ExpandableNotificationRow>("translate") {
+ @Override
+ public void setValue(ExpandableNotificationRow object, float value) {
+ object.setTranslation(value);
+ }
+
+ @Override
+ public Float get(ExpandableNotificationRow object) {
+ return object.getTranslation();
+ }
+ };
+
+ public boolean isGroupExpansionChanging() {
+ if (isChildInGroup()) {
+ return mNotificationParent.isGroupExpansionChanging();
+ }
+ return mGroupExpansionChanging;
+ }
+
+ public void setGroupExpansionChanging(boolean changing) {
+ mGroupExpansionChanging = changing;
+ }
public NotificationContentView getPrivateLayout() {
return mPrivateLayout;
@@ -172,8 +204,8 @@
public void setIconAnimationRunning(boolean running) {
setIconAnimationRunning(running, mPublicLayout);
setIconAnimationRunning(running, mPrivateLayout);
- setIconAnimationRunningForChild(running, mNotificationHeader);
if (mIsSummaryWithChildren) {
+ setIconAnimationRunningForChild(running, mChildrenContainer.getHeaderView());
List<ExpandableNotificationRow> notificationChildren =
mChildrenContainer.getNotificationChildren();
for (int i = 0; i < notificationChildren.size(); i++) {
@@ -235,7 +267,7 @@
updateNotificationColor();
updateClearability();
if (mIsSummaryWithChildren) {
- recreateNotificationHeader();
+ mChildrenContainer.recreateNotificationHeader(mExpandClickListener, mEntry.notification);
mChildrenContainer.onNotificationUpdated();
}
if (mIconAnimationRunning) {
@@ -329,9 +361,6 @@
if (mChildrenContainer != null) {
mChildrenContainer.removeNotification(row);
}
- if (!row.isRemoved()) {
- mHeaderUtil.restoreNotificationHeader(row);
- }
onChildrenCountChanged();
row.setIsChildInGroup(false, null);
}
@@ -352,7 +381,10 @@
boolean childInGroup = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
mNotificationParent = childInGroup ? parent : null;
mPrivateLayout.setIsChildInGroup(childInGroup);
- updateNoBackgroundState();
+ updateBackgroundForGroupState();
+ if (mNotificationParent != null) {
+ mNotificationParent.updateBackgroundForGroupState();
+ }
}
@Override
@@ -544,15 +576,15 @@
}
public NotificationHeaderView getNotificationHeader() {
- if (mNotificationHeader != null) {
- return mNotificationHeader;
+ if (mIsSummaryWithChildren) {
+ return mChildrenContainer.getHeaderView();
}
return mPrivateLayout.getNotificationHeader();
}
private NotificationHeaderView getVisibleNotificationHeader() {
- if (mNotificationHeader != null) {
- return mNotificationHeader;
+ if (mIsSummaryWithChildren) {
+ return mChildrenContainer.getHeaderView();
}
return getShowingLayout().getVisibleNotificationHeader();
}
@@ -568,11 +600,8 @@
public void reInflateViews() {
initDimens();
if (mIsSummaryWithChildren) {
- removeView(mNotificationHeader);
- mNotificationHeader = null;
- recreateNotificationHeader();
if (mChildrenContainer != null) {
- mChildrenContainer.reInflateViews();
+ mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.notification);
}
}
if (mGuts != null) {
@@ -646,9 +675,6 @@
continue;
}
mChildrenContainer.removeNotification(row);
- if (!row.isRemoved()) {
- mHeaderUtil.restoreNotificationHeader(row);
- }
row.setIsChildInGroup(false, null);
}
onChildrenCountChanged();
@@ -684,8 +710,13 @@
return mRemoved;
}
- public void setRemoved(boolean removed) {
- mRemoved = removed;
+ public void setRemoved() {
+ mRemoved = true;
+
+ mPrivateLayout.setRemoved();
+ if (mChildrenContainer != null) {
+ mChildrenContainer.setRemoved();
+ }
}
public NotificationChildrenContainer getChildrenContainer() {
@@ -709,6 +740,8 @@
mMaxHeadsUpHeightLegacy = getFontScaledHeight(
R.dimen.notification_max_heads_up_height_legacy);
mMaxHeadsUpHeight = getFontScaledHeight(R.dimen.notification_max_heads_up_height);
+ mIncreasedPaddingBetweenElements = getResources()
+ .getDimensionPixelSize(R.dimen.notification_divider_height_increased);
}
/**
@@ -804,17 +837,13 @@
mTranslateableViews.remove(mGutsStub);
}
- private void setTranslationForOutline(float translationX) {
- setOutlineRect(false, translationX, getTop(), getRight() + translationX, getBottom());
- }
-
public void resetTranslation() {
if (mTranslateableViews != null) {
for (int i = 0; i < mTranslateableViews.size(); i++) {
mTranslateableViews.get(i).setTranslationX(0);
}
- setTranslationForOutline(0);
}
+ invalidateOutline();
if (mSettingsIconRow != null) {
mSettingsIconRow.resetState();
}
@@ -824,8 +853,7 @@
if (mTranslateAnim != null) {
mTranslateAnim.cancel();
}
- mTranslateAnim = (AnimatorSet) getTranslateViewAnimator(leftTarget,
- null /* updateListener */);
+ mTranslateAnim = getTranslateViewAnimator(leftTarget, null /* updateListener */);
if (mTranslateAnim != null) {
mTranslateAnim.start();
}
@@ -843,7 +871,7 @@
mTranslateableViews.get(i).setTranslationX(translationX);
}
}
- setTranslationForOutline(translationX);
+ invalidateOutline();
if (mSettingsIconRow != null) {
mSettingsIconRow.updateSettingsIcons(translationX, getMeasuredWidth());
}
@@ -867,48 +895,29 @@
// No translation if guts are exposed.
return null;
}
- AnimatorSet set = new AnimatorSet();
- if (mTranslateableViews != null) {
- for (int i = 0; i < mTranslateableViews.size(); i++) {
- final View animView = mTranslateableViews.get(i);
- final ObjectAnimator translateAnim = ObjectAnimator.ofFloat(
- animView, "translationX", leftTarget);
- if (i == 0) {
- translateAnim.addUpdateListener(new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- setTranslationForOutline((float) animation.getAnimatedValue());
- if (mSettingsIconRow != null) {
- mSettingsIconRow.updateSettingsIcons(
- (float) animation.getAnimatedValue(), getMeasuredWidth());
- }
- }
- });
- if (listener != null) {
- translateAnim.addUpdateListener(listener);
- }
- translateAnim.addListener(new AnimatorListenerAdapter() {
- boolean cancelled = false;
-
- @Override
- public void onAnimationCancel(Animator anim) {
- cancelled = true;
- }
-
- @Override
- public void onAnimationEnd(Animator anim) {
- if (!cancelled && mSettingsIconRow != null && leftTarget == 0) {
- mSettingsIconRow.resetState();
- mTranslateAnim = null;
- }
- }
- });
- }
- set.play(translateAnim);
- }
+ final ObjectAnimator translateAnim = ObjectAnimator.ofFloat(this, TRANSLATE_CONTENT,
+ leftTarget);
+ if (listener != null) {
+ translateAnim.addUpdateListener(listener);
}
- mTranslateAnim = set;
- return set;
+ translateAnim.addListener(new AnimatorListenerAdapter() {
+ boolean cancelled = false;
+
+ @Override
+ public void onAnimationCancel(Animator anim) {
+ cancelled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator anim) {
+ if (!cancelled && mSettingsIconRow != null && leftTarget == 0) {
+ mSettingsIconRow.resetState();
+ mTranslateAnim = null;
+ }
+ }
+ });
+ mTranslateAnim = translateAnim;
+ return translateAnim;
}
public float getSpaceForGear() {
@@ -937,9 +946,8 @@
if (mChildrenContainer != null) {
mChildrenContainer.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
: INVISIBLE);
- }
- if (mNotificationHeader != null) {
- mNotificationHeader.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
+ mChildrenContainer.updateHeaderVisibility(!mShowingPublic && mIsSummaryWithChildren
+ ? VISIBLE
: INVISIBLE);
}
// The limits might have changed if the view suddenly became a group or vice versa
@@ -969,7 +977,6 @@
}
if (mIsSummaryWithChildren) {
mChildrenContainer.setDark(dark, fade, delay);
- mNotificationHeaderWrapper.setDark(dark, fade, delay);
}
}
@@ -1020,7 +1027,9 @@
public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) {
mFalsingManager.setNotificationExpanded();
if (mIsSummaryWithChildren && !mShowingPublic && allowChildExpansion) {
+ final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
mGroupManager.setGroupExpanded(mStatusBarNotification, userExpanded);
+ logExpansionEvent(true /* userAction */, wasExpanded);
return;
}
if (userExpanded && !mExpandable) return;
@@ -1044,6 +1053,9 @@
mPrivateLayout.setUserExpanding(userLocked);
if (mIsSummaryWithChildren) {
mChildrenContainer.setUserLocked(userLocked);
+ if (userLocked) {
+ updateBackgroundForGroupState();
+ }
}
}
@@ -1123,30 +1135,28 @@
}
}
- private boolean isGroupExpanded() {
+ public boolean isGroupExpanded() {
return mGroupManager.isGroupExpanded(mStatusBarNotification);
}
- /**
- * @return whether this view has a header on the top of the content
- */
- private boolean hasNotificationHeader() {
- return mIsSummaryWithChildren;
- }
-
private void onChildrenCountChanged() {
mIsSummaryWithChildren = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS
- && mChildrenContainer != null && mChildrenContainer.getChildCount() > 0;
- if (mIsSummaryWithChildren) {
- if (mNotificationHeader == null) {
- recreateNotificationHeader();
- }
+ && mChildrenContainer != null && mChildrenContainer.getNotificationChildCount() > 0;
+ if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() == null) {
+ mChildrenContainer.recreateNotificationHeader(mExpandClickListener,
+ mEntry.notification);
}
mPrivateLayout.updateExpandButtons(isExpandable());
updateChildrenHeaderAppearance();
updateChildrenVisibility();
}
+ public void updateChildrenHeaderAppearance() {
+ if (mChildrenContainer != null) {
+ mChildrenContainer.updateChildrenHeaderAppearance();
+ }
+ }
+
/**
* Check whether the view state is currently expanded. This is given by the system in {@link
* #setSystemExpanded(boolean)} and can be overridden by user expansion or
@@ -1251,8 +1261,8 @@
}
private void animateShowingPublic(long delay, long duration) {
- View[] privateViews = mIsSummaryWithChildren ?
- new View[] {mChildrenContainer, mNotificationHeader}
+ View[] privateViews = mIsSummaryWithChildren
+ ? new View[] {mChildrenContainer}
: new View[] {mPrivateLayout};
View[] publicViews = new View[] {mPublicLayout};
View[] hiddenChildren = mShowingPublic ? privateViews : publicViews;
@@ -1302,9 +1312,6 @@
public void setChildrenExpanded(boolean expanded, boolean animate) {
mChildrenExpanded = expanded;
- if (mNotificationHeader != null) {
- mNotificationHeader.setExpanded(expanded);
- }
if (mChildrenContainer != null) {
mChildrenContainer.setChildrenExpanded(expanded);
}
@@ -1349,6 +1356,14 @@
}
@Override
+ public int getExtraBottomPadding() {
+ if (mIsSummaryWithChildren && isGroupExpanded()) {
+ return mIncreasedPaddingBetweenElements;
+ }
+ return 0;
+ }
+
+ @Override
public void setActualHeight(int height, boolean notifyListeners) {
super.setActualHeight(height, notifyListeners);
if (mGuts != null && mGuts.areGutsExposed()) {
@@ -1406,33 +1421,6 @@
}
}
- private void recreateNotificationHeader() {
- final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
- getStatusBarNotification().getNotification());
- final RemoteViews header = builder.makeNotificationHeader();
- if (mNotificationHeader == null) {
- mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
- final View expandButton = mNotificationHeader.findViewById(
- com.android.internal.R.id.expand_button);
- expandButton.setVisibility(VISIBLE);
- mNotificationHeader.setOnClickListener(mExpandClickListener);
- mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(),
- mNotificationHeader, this);
- addView(mNotificationHeader, indexOfChild(mChildrenContainer) + 1);
- mTranslateableViews.add(mNotificationHeader);
- } else {
- header.reapply(getContext(), mNotificationHeader);
- mNotificationHeaderWrapper.notifyContentUpdated(mEntry.notification);
- }
- updateChildrenHeaderAppearance();
- }
-
- public void updateChildrenHeaderAppearance() {
- if (mIsSummaryWithChildren) {
- mHeaderUtil.updateChildrenHeaderAppearance();
- }
- }
-
public boolean isMaxExpandHeightInitialized() {
return mMaxExpandHeight != 0;
}
@@ -1451,19 +1439,50 @@
@Override
protected void updateBackgroundTint() {
super.updateBackgroundTint();
- updateNoBackgroundState();
+ updateBackgroundForGroupState();
if (mIsSummaryWithChildren) {
List<ExpandableNotificationRow> notificationChildren =
mChildrenContainer.getNotificationChildren();
for (int i = 0; i < notificationChildren.size(); i++) {
ExpandableNotificationRow child = notificationChildren.get(i);
- child.updateNoBackgroundState();
+ child.updateBackgroundForGroupState();
}
}
}
- private void updateNoBackgroundState() {
- mShowNoBackground = isChildInGroup() && hasSameBgColor(mNotificationParent);
+ /**
+ * Called when a group has finished animating from collapsed or expanded state.
+ */
+ public void onFinishedExpansionChange() {
+ mGroupExpansionChanging = false;
+ updateBackgroundForGroupState();
+ }
+
+ /**
+ * Updates the parent and children backgrounds in a group based on the expansion state.
+ */
+ public void updateBackgroundForGroupState() {
+ if (mIsSummaryWithChildren) {
+ // Only when the group has finished expanding do we hide its background.
+ mShowNoBackground = isGroupExpanded() && !isGroupExpansionChanging() && !isUserLocked();
+ mChildrenContainer.updateHeaderForExpansion(mShowNoBackground);
+ List<ExpandableNotificationRow> children = mChildrenContainer.getNotificationChildren();
+ for (int i = 0; i < children.size(); i++) {
+ children.get(i).updateBackgroundForGroupState();
+ }
+ } else if (isChildInGroup()) {
+ final int childColor = getShowingLayout().getBackgroundColorForExpansionState();
+ // Only show a background if the group is expanded OR if it is expanding / collapsing
+ // and has a custom background color
+ final boolean showBackground = isGroupExpanded()
+ || ((mNotificationParent.isGroupExpansionChanging()
+ || mNotificationParent.isUserLocked()) && childColor != 0);
+ mShowNoBackground = !showBackground;
+ } else {
+ // Only children or parents ever need no background.
+ mShowNoBackground = false;
+ }
+ updateOutline();
updateBackground();
}
@@ -1472,6 +1491,14 @@
mLoggingKey = key;
}
+ public void onExpandedByGesture(boolean userExpanded) {
+ int event = MetricsEvent.ACTION_NOTIFICATION_GESTURE_EXPANDER;
+ if (mGroupManager.isSummaryOfGroup(getStatusBarNotification())) {
+ event = MetricsEvent.ACTION_NOTIFICATION_GROUP_GESTURE_EXPANDER;
+ }
+ MetricsLogger.action(mContext, event, userExpanded);
+ }
+
@Override
public float getIncreasedPaddingAmount() {
if (mIsSummaryWithChildren) {
@@ -1496,7 +1523,10 @@
}
private void logExpansionEvent(boolean userAction, boolean wasExpanded) {
- final boolean nowExpanded = isExpanded();
+ boolean nowExpanded = isExpanded();
+ if (mIsSummaryWithChildren) {
+ nowExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
+ }
if (wasExpanded != nowExpanded && mLogger != null) {
mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded) ;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
index f98e87d..9d9f3b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
@@ -33,22 +33,25 @@
private boolean mCustomOutline;
private float mOutlineAlpha = -1f;
+ ViewOutlineProvider mProvider = new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ int translation = (int) getTranslation();
+ if (!mCustomOutline) {
+ outline.setRect(translation,
+ mClipTopAmount,
+ getWidth() + translation,
+ Math.max(getActualHeight(), mClipTopAmount));
+ } else {
+ outline.setRect(mOutlineRect);
+ }
+ outline.setAlpha(mOutlineAlpha);
+ }
+ };
+
public ExpandableOutlineView(Context context, AttributeSet attrs) {
super(context, attrs);
- setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- if (!mCustomOutline) {
- outline.setRect(0,
- mClipTopAmount,
- getWidth(),
- Math.max(getActualHeight(), mClipTopAmount));
- } else {
- outline.setRect(mOutlineRect);
- }
- outline.setAlpha(mOutlineAlpha);
- }
- });
+ setOutlineProvider(mProvider);
}
@Override
@@ -87,17 +90,30 @@
@Override
public int getOutlineTranslation() {
- return mCustomOutline ? mOutlineRect.left : 0;
+ return mCustomOutline ? mOutlineRect.left : (int) getTranslation();
+ }
+
+ public void updateOutline() {
+ if (mCustomOutline) {
+ return;
+ }
+ boolean hasOutline = true;
+ if (isChildInGroup()) {
+ hasOutline = isGroupExpanded() && !isGroupExpansionChanging();
+ } else if (isSummaryWithChildren()) {
+ hasOutline = !isGroupExpanded() || isGroupExpansionChanging();
+ }
+ setOutlineProvider(hasOutline ? mProvider : null);
+ }
+
+ public boolean isOutlineShowing() {
+ ViewOutlineProvider op = getOutlineProvider();
+ return op != null;
}
protected void setOutlineRect(float left, float top, float right, float bottom) {
- setOutlineRect(true, left, top, right, bottom);
- }
-
- protected void setOutlineRect(boolean clipToOutline, float left, float top, float right,
- float bottom) {
mCustomOutline = true;
- setClipToOutline(clipToOutline);
+ setClipToOutline(true);
mOutlineRect.set((int) left, (int) top, (int) right, (int) bottom);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 280663b..2c302ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -323,7 +323,7 @@
if (top >= getActualHeight()) {
top = getActualHeight() - 1;
}
- mClipRect.set(0, top, getWidth(), getActualHeight());
+ mClipRect.set(0, top, getWidth(), getActualHeight() + getExtraBottomPadding());
setClipBounds(mClipRect);
} else {
setClipBounds(null);
@@ -411,6 +411,28 @@
}
/**
+ * @return padding used to alter how much of the view is clipped.
+ */
+ public int getExtraBottomPadding() {
+ return 0;
+ }
+
+ /**
+ * @return true if the group's expansion state is changing, false otherwise.
+ */
+ public boolean isGroupExpansionChanging() {
+ return false;
+ }
+
+ public boolean isGroupExpanded() {
+ return false;
+ }
+
+ public boolean isChildInGroup() {
+ return false;
+ }
+
+ /**
* A listener notifying when {@link #getActualHeight} changes.
*/
public interface OnHeightChangedListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 70ea55c..d6c02e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -71,7 +71,6 @@
private HybridGroupManager mHybridGroupManager;
private int mClipTopAmount;
private int mContentHeight;
- private int mUnrestrictedContentHeight;
private int mVisibleType = VISIBLE_TYPE_CONTRACTED;
private boolean mDark;
private boolean mAnimate;
@@ -264,6 +263,7 @@
invalidateOutline();
selectLayout(false /* animate */, mForceSelectNextLayout /* force */);
mForceSelectNextLayout = false;
+ updateExpandButtons(mExpandable);
}
@Override
@@ -360,7 +360,9 @@
private void setVisible(final boolean isVisible) {
if (isVisible) {
-
+ // This call can happen multiple times, but removing only removes a single one.
+ // We therefore need to remove the old one.
+ getViewTreeObserver().removeOnPreDrawListener(mEnableAnimationPredrawListener);
// We only animate if we are drawn at least once, otherwise the view might animate when
// it's shown the first time
getViewTreeObserver().addOnPreDrawListener(mEnableAnimationPredrawListener);
@@ -371,8 +373,7 @@
}
public void setContentHeight(int contentHeight) {
- mContentHeight = Math.max(Math.min(contentHeight, getHeight()), getMinHeight());;
- mUnrestrictedContentHeight = Math.max(contentHeight, getMinHeight());
+ mContentHeight = Math.max(Math.min(contentHeight, getHeight()), getMinHeight());
selectLayout(mAnimate /* animate */, false /* force */);
int minHeightHint = getMinContentHeightHint();
@@ -596,7 +597,21 @@
mContainingNotification.setContentBackground(customBackgroundColor, animate, this);
}
- private int getBackgroundColor(int visibleType) {
+ public int getVisibleType() {
+ return mVisibleType;
+ }
+
+ public int getBackgroundColorForExpansionState() {
+ // When expanding or user locked we want the new type, when collapsing we want
+ // the original type
+ final int visibleType = (mContainingNotification.isGroupExpanded()
+ || mContainingNotification.isUserLocked())
+ ? calculateVisibleType()
+ : getVisibleType();
+ return getBackgroundColor(visibleType);
+ }
+
+ public int getBackgroundColor(int visibleType) {
NotificationViewWrapper currentVisibleWrapper = getVisibleWrapper(visibleType);
int customBackgroundColor = 0;
if (currentVisibleWrapper != null) {
@@ -704,7 +719,7 @@
/**
* @return one of the static enum types in this view, calculated form the current state
*/
- private int calculateVisibleType() {
+ public int calculateVisibleType() {
if (mUserExpanding) {
int height = !mIsChildInGroup || isGroupExpanded()
|| mContainingNotification.isExpanded(true /* allowOnKeyguard */)
@@ -1046,4 +1061,13 @@
public HybridNotificationView getSingleLineView() {
return mSingleLineView;
}
+
+ public void setRemoved() {
+ if (mExpandedRemoteInput != null) {
+ mExpandedRemoteInput.setRemoved();
+ }
+ if (mHeadsUpRemoteInput != null) {
+ mHeadsUpRemoteInput.setRemoved();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 4650a1f..b523a11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -23,6 +23,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Handler;
@@ -70,6 +71,8 @@
private ImageView mAutoButton;
private ColorStateList mActiveSliderTint;
private ColorStateList mInactiveSliderTint;
+ private float mActiveSliderAlpha = 1.0f;
+ private float mInactiveSliderAlpha;
private TextView mImportanceSummary;
private TextView mImportanceTitle;
private boolean mAuto;
@@ -100,6 +103,11 @@
}
}
};
+ final TypedArray ta =
+ context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Theme, 0, 0);
+ mInactiveSliderAlpha =
+ ta.getFloat(com.android.internal.R.styleable.Theme_disabledAlpha, 0.5f);
+ ta.recycle();
}
public void resetFalsingCheck() {
@@ -299,13 +307,12 @@
private void applyAuto() {
mSeekBar.setEnabled(!mAuto);
- final ColorStateList sliderTint = mAuto ? mInactiveSliderTint : mActiveSliderTint;
final ColorStateList starTint = mAuto ? mActiveSliderTint : mInactiveSliderTint;
+ final float alpha = mAuto ? mInactiveSliderAlpha : mActiveSliderAlpha;
Drawable icon = mAutoButton.getDrawable().mutate();
icon.setTintList(starTint);
mAutoButton.setImageDrawable(icon);
- mSeekBar.setProgressTintList(sliderTint);
- mSeekBar.setThumbTintList(sliderTint);
+ mSeekBar.setAlpha(alpha);
if (mAuto) {
mSeekBar.setProgress(mNotificationImportance);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
index 7575dc8..7f95d48 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
@@ -90,7 +90,7 @@
private final ArrayList<HeaderProcessor> mComparators = new ArrayList<>();
private final HashSet<Integer> mDividers = new HashSet<>();
- NotificationHeaderUtil(ExpandableNotificationRow row) {
+ public NotificationHeaderUtil(ExpandableNotificationRow row) {
mRow = row;
// To hide the icons if they are the same and the color is the same
mComparators.add(new HeaderProcessor(mRow,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index bc33b30..cdfdad4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -18,6 +18,7 @@
import android.app.Notification;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
@@ -25,6 +26,7 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
+import android.os.Parcelable;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.AttributeSet;
@@ -325,8 +327,20 @@
public static String contentDescForNotification(Context c, Notification n) {
- Notification.Builder builder = Notification.Builder.recoverBuilder(c, n);
- String appName = builder.loadHeaderAppName();
+ String appName = "";
+ try {
+ Notification.Builder builder = Notification.Builder.recoverBuilder(c, n);
+ appName = builder.loadHeaderAppName();
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Unable to recover builder", e);
+ // Trying to get the app name from the app info instead.
+ Parcelable appInfo = n.extras.getParcelable(
+ Notification.EXTRA_BUILDER_APPLICATION_INFO);
+ if (appInfo instanceof ApplicationInfo) {
+ appName = String.valueOf(((ApplicationInfo) appInfo).loadLabel(
+ c.getPackageManager()));
+ }
+ }
CharSequence title = n.extras.getCharSequence(Notification.EXTRA_TITLE);
CharSequence ticker = n.tickerText;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java
index b66e9f3..8463e06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java
@@ -109,9 +109,6 @@
@Override
public void recycle() {
super.recycle();
- if (mWorkProfileState != null) {
- mWorkProfileState.recycle();
- }
sInstancePool.release(this);
}
@@ -120,6 +117,10 @@
super.reset();
mExpandButton = null;
mWorkProfileState = null;
+ if (mWorkProfileState != null) {
+ mWorkProfileState.recycle();
+ mWorkProfileState = null;
+ }
}
public void setVisible(boolean visible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 4e643f0..7d3da1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -463,9 +463,7 @@
mTransformedView.animate().cancel();
mTransformedView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
mTransformedView.setAlpha(visible ? 1.0f : 0.0f);
- if (visible) {
- resetTransformedView();
- }
+ resetTransformedView();
}
public void prepareFadeIn() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index 0df1204..9ecff18d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -323,12 +323,14 @@
: group.summary.row;
}
- public void toggleGroupExpansion(StatusBarNotification sbn) {
+ /** @return group expansion state after toggling. */
+ public boolean toggleGroupExpansion(StatusBarNotification sbn) {
NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
if (group == null) {
- return;
+ return false;
}
setGroupExpanded(group, !group.expanded);
+ return group.expanded;
}
private boolean isIsolated(StatusBarNotification sbn) {
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 6a37099..522f250 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -220,6 +220,20 @@
super.onFinishInflate();
mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header);
mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view);
+ mClockView = (TextView) findViewById(R.id.clock_view);
+
+ mNotificationContainerParent = (NotificationsQuickSettingsContainer)
+ findViewById(R.id.notification_container_parent);
+ mNotificationStackScroller = (NotificationStackScrollLayout)
+ findViewById(R.id.notification_stack_scroller);
+ mNotificationStackScroller.setOnHeightChangedListener(this);
+ mNotificationStackScroller.setOverscrollTopChangedListener(this);
+ mNotificationStackScroller.setOnEmptySpaceClickListener(this);
+ mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
+ mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
+ mAfforanceHelper = new KeyguardAffordanceHelper(this, getContext());
+ mLastOrientation = getResources().getConfiguration().orientation;
+
mQsAutoReinflateContainer =
(AutoReinflateContainer) findViewById(R.id.qs_auto_reinflate_container);
mQsAutoReinflateContainer.addInflateListener(new InflateListener() {
@@ -229,32 +243,20 @@
mQsContainer.setPanelView(NotificationPanelView.this);
mQsContainer.getHeader().findViewById(R.id.expand_indicator)
.setOnClickListener(NotificationPanelView.this);
- }
- });
- mClockView = (TextView) findViewById(R.id.clock_view);
- mNotificationContainerParent = (NotificationsQuickSettingsContainer)
- findViewById(R.id.notification_container_parent);
- mNotificationStackScroller = (NotificationStackScrollLayout)
- findViewById(R.id.notification_stack_scroller);
- mNotificationStackScroller.setOnHeightChangedListener(this);
- mNotificationStackScroller.setOverscrollTopChangedListener(this);
- mNotificationStackScroller.setOnEmptySpaceClickListener(this);
- mNotificationStackScroller.setQsContainer(mQsContainer);
- mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
- mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
- mAfforanceHelper = new KeyguardAffordanceHelper(this, getContext());
- mLastOrientation = getResources().getConfiguration().orientation;
- // recompute internal state when qspanel height changes
- mQsContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- final int height = bottom - top;
- final int oldHeight = oldBottom - oldTop;
- if (height != oldHeight) {
- onQsHeightChanged();
- }
+ // recompute internal state when qspanel height changes
+ mQsContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ final int height = bottom - top;
+ final int oldHeight = oldBottom - oldTop;
+ if (height != oldHeight) {
+ onQsHeightChanged();
+ }
+ }
+ });
+ mNotificationStackScroller.setQsContainer(mQsContainer);
}
});
}
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 073994f..9208134 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -263,6 +263,14 @@
* This affects the status bar UI. */
private static final boolean FREEFORM_WINDOW_MANAGEMENT;
+ /**
+ * How long to wait before auto-dismissing a notification that was kept for remote input, and
+ * has now sent a remote input. We auto-dismiss, because the app may not see a reason to cancel
+ * these given that they technically don't exist anymore. We wait a bit in case the app issues
+ * an update.
+ */
+ private static final int REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY = 200;
+
static {
boolean onlyCoreApps;
boolean freeformWindowManagement;
@@ -1181,16 +1189,24 @@
mIconPolicy.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mRemoteInputController.addCallback(mStatusBarKeyguardViewManager);
- if (FORCE_REMOTE_INPUT_HISTORY) {
- mRemoteInputController.addCallback(new RemoteInputController.Callback() {
- @Override
- public void onRemoteInputSent(Entry entry) {
- if (mKeysKeptForRemoteInput.contains(entry.key)) {
- removeNotification(entry.key, null);
- }
+ mRemoteInputController.addCallback(new RemoteInputController.Callback() {
+ @Override
+ public void onRemoteInputSent(Entry entry) {
+ if (FORCE_REMOTE_INPUT_HISTORY && mKeysKeptForRemoteInput.contains(entry.key)) {
+ removeNotification(entry.key, null);
+ } else if (mRemoteInputEntriesToRemoveOnCollapse.contains(entry)) {
+ // We're currently holding onto this notification, but from the apps point of
+ // view it is already canceled, so we'll need to cancel it on the apps behalf
+ // after sending - unless the app posts an update in the mean time, so wait a
+ // bit.
+ mHandler.postDelayed(() -> {
+ if (mRemoteInputEntriesToRemoveOnCollapse.remove(entry)) {
+ removeNotification(entry.key, null);
+ }
+ }, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY);
}
- });
- }
+ }
+ });
mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
mLightStatusBarController.setFingerprintUnlockController(mFingerprintUnlockController);
@@ -1507,8 +1523,15 @@
return;
}
Entry entry = mNotificationData.get(key);
+
+ if (entry != null && mRemoteInputController.isRemoteInputActive(entry)) {
+ mLatestRankingMap = ranking;
+ mRemoteInputEntriesToRemoveOnCollapse.add(entry);
+ return;
+ }
+
if (entry != null && entry.row != null) {
- entry.row.setRemoved(true);
+ entry.row.setRemoved();
}
// Let's remove the children if this was a summary
handleGroupSummaryRemoved(key, ranking);
@@ -1556,7 +1579,7 @@
toRemove.get(i).setKeepInParent(true);
// we need to set this state earlier as otherwise we might generate some weird
// animations
- toRemove.get(i).setRemoved(true);
+ toRemove.get(i).setRemoved();
}
for (int i = 0; i < toRemove.size(); i++) {
removeNotification(toRemove.get(i).getStatusBarNotification().getKey(), ranking);
@@ -1568,6 +1591,15 @@
}
@Override
+ protected void performRemoveNotification(StatusBarNotification n, boolean removeView) {
+ Entry entry = mNotificationData.get(n.getKey());
+ if (mRemoteInputController.isRemoteInputActive(entry)) {
+ mRemoteInputController.removeRemoteInput(entry);
+ }
+ super.performRemoveNotification(n, removeView);
+ }
+
+ @Override
protected void refreshLayout(int layoutDirection) {
if (mNavigationBarView != null) {
mNavigationBarView.setLayoutDirection(layoutDirection);
@@ -2464,6 +2496,26 @@
public void setPanelExpanded(boolean isExpanded) {
mStatusBarWindowManager.setPanelExpanded(isExpanded);
+
+ if (isExpanded && getBarState() != StatusBarState.KEYGUARD) {
+ if (DEBUG) {
+ Log.v(TAG, "clearing notification effects from setPanelExpanded");
+ }
+ clearNotificationEffects();
+ }
+
+ if (!isExpanded) {
+ removeRemoteInputEntriesKeptUntilCollapsed();
+ }
+ }
+
+ private void removeRemoteInputEntriesKeptUntilCollapsed() {
+ for (int i = 0; i < mRemoteInputEntriesToRemoveOnCollapse.size(); i++) {
+ Entry entry = mRemoteInputEntriesToRemoveOnCollapse.valueAt(i);
+ mRemoteInputController.removeRemoteInput(entry);
+ removeNotification(entry.key, mLatestRankingMap);
+ }
+ mRemoteInputEntriesToRemoveOnCollapse.clear();
}
public void onScreenTurnedOff() {
@@ -4207,6 +4259,9 @@
|| (state == StatusBarState.SHADE && isGoingToNotificationShade()))) {
clearNotificationEffects();
}
+ if (state == StatusBarState.KEYGUARD) {
+ removeRemoteInputEntriesKeptUntilCollapsed();
+ }
mState = state;
mGroupManager.setStatusBarState(state);
mFalsingManager.setStatusBarState(state);
@@ -4284,6 +4339,8 @@
// ---------------------- DragDownHelper.OnDragDownListener ------------------------------------
+
+ /* Only ever called as a consequence of a lockscreen expansion gesture. */
@Override
public boolean onDraggedDown(View startingChild, int dragLengthY) {
if (hasActiveNotifications()) {
@@ -4294,6 +4351,10 @@
// We have notifications, go to locked shade.
goToLockedShade(startingChild);
+ if (startingChild instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) startingChild;
+ row.onExpandedByGesture(true /* drag down is always an open */);
+ }
return true;
} else {
@@ -4335,6 +4396,9 @@
if (expandView instanceof ExpandableNotificationRow) {
row = (ExpandableNotificationRow) expandView;
row.setUserExpanded(true /* userExpanded */, true /* allowChildExpansion */);
+ // Indicate that the group expansion is changing at this time -- this way the group
+ // and children backgrounds / divider animations will look correct.
+ row.setGroupExpansionChanging(true);
}
boolean fullShadeNeedsBouncer = !userAllowsPrivateNotificationsInPublic(mCurrentUserId)
|| !mShowLockscreenNotifications || mFalsingManager.shouldEnforceBouncer();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 095265a..2f522f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -73,6 +73,7 @@
private ScrollContainer mScrollContainer;
private View mScrollContainerChild;
+ private boolean mRemoved;
public RemoteInputView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -171,7 +172,12 @@
public void onDefocus() {
mController.removeRemoteInput(mEntry);
mEntry.remoteInputText = mEditText.getText();
- setVisibility(INVISIBLE);
+
+ // During removal, we get reattached and lose focus. Not hiding in that
+ // case to prevent flicker.
+ if (!mRemoved) {
+ setVisibility(INVISIBLE);
+ }
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_CLOSE,
mEntry.notification.getPackageName());
}
@@ -347,6 +353,10 @@
return mPendingIntent;
}
+ public void setRemoved() {
+ mRemoved = true;
+ }
+
/**
* An EditText that changes appearance based on whether it's focusable and becomes
* un-focusable whenever the user navigates away from it or it becomes invisible.
@@ -416,6 +426,15 @@
}
@Override
+ public boolean onCheckIsTextEditor() {
+ // Stop being editable while we're being removed. During removal, we get reattached,
+ // and editable views get their spellchecking state re-evaluated which is too costly
+ // during the removal animation.
+ boolean flyingOut = mRemoteInputView != null && mRemoteInputView.mRemoved;
+ return !flyingOut && super.onCheckIsTextEditor();
+ }
+
+ @Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
final InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index e919d5c..cb0b848 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -16,21 +16,28 @@
package com.android.systemui.statusbar.stack;
+import android.app.Notification;
import android.content.Context;
import android.content.res.Configuration;
+import android.graphics.drawable.ColorDrawable;
+import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
import android.view.LayoutInflater;
+import android.view.NotificationHeaderView;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.RemoteViews;
import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.ViewInvertHelper;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationHeaderUtil;
import com.android.systemui.statusbar.notification.HybridGroupManager;
import com.android.systemui.statusbar.notification.HybridNotificationView;
import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.NotificationViewWrapper;
import com.android.systemui.statusbar.phone.NotificationPanelView;
import java.util.ArrayList;
@@ -51,7 +58,7 @@
private int mChildPadding;
private int mDividerHeight;
private int mMaxNotificationHeight;
- private int mNotificationHeaderHeight;
+ private int mNotificationHeaderMargin;
private int mNotificatonTopPadding;
private float mCollapsedBottompadding;
private ViewInvertHelper mOverflowInvertHelper;
@@ -63,6 +70,12 @@
private boolean mUserLocked;
private int mActualHeight;
private boolean mNeverAppliedGroupState;
+ private int mHeaderHeight;
+
+ private NotificationHeaderView mNotificationHeader;
+ private NotificationViewWrapper mNotificationHeaderWrapper;
+ private NotificationHeaderUtil mHeaderUtil;
+ private ViewState mHeaderViewState;
public NotificationChildrenContainer(Context context) {
this(context, null);
@@ -88,9 +101,10 @@
R.dimen.notification_children_padding);
mDividerHeight = Math.max(1, getResources().getDimensionPixelSize(
R.dimen.notification_divider_height));
+ mHeaderHeight = getResources().getDimensionPixelSize(R.dimen.notification_header_height);
mMaxNotificationHeight = getResources().getDimensionPixelSize(
R.dimen.notification_max_height);
- mNotificationHeaderHeight = getResources().getDimensionPixelSize(
+ mNotificationHeaderMargin = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_content_margin_top);
mNotificatonTopPadding = getResources().getDimensionPixelSize(
R.dimen.notification_children_container_top_padding);
@@ -112,6 +126,10 @@
mOverflowNumber.layout(getWidth() - mOverflowNumber.getMeasuredWidth(), 0, getWidth(),
mOverflowNumber.getMeasuredHeight());
}
+ if (mNotificationHeader != null) {
+ mNotificationHeader.layout(0, 0, mNotificationHeader.getMeasuredWidth(),
+ mNotificationHeader.getMeasuredHeight());
+ }
}
@Override
@@ -131,7 +149,7 @@
newHeightSpec);
}
int dividerHeightSpec = MeasureSpec.makeMeasureSpec(mDividerHeight, MeasureSpec.EXACTLY);
- int height = mNotificationHeaderHeight + mNotificatonTopPadding;
+ int height = mNotificationHeaderMargin + mNotificatonTopPadding;
int childCount = Math.min(mChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
int collapsedChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
int overflowIndex = childCount > collapsedChildren ? collapsedChildren - 1 : -1;
@@ -155,6 +173,12 @@
if (heightMode != MeasureSpec.UNSPECIFIED) {
height = Math.min(height, size);
}
+
+ if (mNotificationHeader != null) {
+ int headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
+ mNotificationHeader.measure(widthMeasureSpec, headerHeightSpec);
+ }
+
setMeasuredDimension(width, height);
}
@@ -201,6 +225,41 @@
row.setSystemChildExpanded(false);
row.setUserLocked(false);
updateGroupOverflow();
+ if (!row.isRemoved()) {
+ mHeaderUtil.restoreNotificationHeader(row);
+ }
+ }
+
+ /**
+ * @return The number of notification children in the container.
+ */
+ public int getNotificationChildCount() {
+ return mChildren.size();
+ }
+
+ public void recreateNotificationHeader(OnClickListener listener, StatusBarNotification notification) {
+ final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
+ mNotificationParent.getStatusBarNotification().getNotification());
+ final RemoteViews header = builder.makeNotificationHeader();
+ if (mNotificationHeader == null) {
+ mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
+ final View expandButton = mNotificationHeader.findViewById(
+ com.android.internal.R.id.expand_button);
+ expandButton.setVisibility(VISIBLE);
+ mNotificationHeader.setOnClickListener(listener);
+ mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(),
+ mNotificationHeader, mNotificationParent);
+ addView(mNotificationHeader, 0);
+ invalidate();
+ } else {
+ header.reapply(getContext(), mNotificationHeader);
+ mNotificationHeaderWrapper.notifyContentUpdated(notification);
+ }
+ updateChildrenHeaderAppearance();
+ }
+
+ public void updateChildrenHeaderAppearance() {
+ mHeaderUtil.updateChildrenHeaderAppearance();
}
public void updateGroupOverflow() {
@@ -210,7 +269,7 @@
mOverflowNumber = mHybridGroupManager.bindOverflowNumber(
mOverflowNumber, childCount - maxAllowedVisibleChildren);
if (mOverflowInvertHelper == null) {
- mOverflowInvertHelper= new ViewInvertHelper(mOverflowNumber,
+ mOverflowInvertHelper = new ViewInvertHelper(mOverflowNumber,
NotificationPanelView.DOZE_ANIMATION_DURATION);
}
if (mGroupOverFlowState == null) {
@@ -300,7 +359,7 @@
* in @param maxAllowedVisibleChildren
*/
private int getIntrinsicHeight(float maxAllowedVisibleChildren) {
- int intrinsicHeight = mNotificationHeaderHeight;
+ int intrinsicHeight = mNotificationHeaderMargin;
int visibleChildren = 0;
int childCount = mChildren.size();
boolean firstChild = true;
@@ -353,7 +412,7 @@
*/
public void getState(StackScrollState resultState, StackViewState parentState) {
int childCount = mChildren.size();
- int yPosition = mNotificationHeaderHeight;
+ int yPosition = mNotificationHeaderMargin;
boolean firstChild = true;
int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren();
int lastVisibleIndex = maxAllowedVisibleChildren - 1;
@@ -363,12 +422,16 @@
expandFactor = getGroupExpandFraction();
firstOverflowIndex = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
}
+
+ boolean childrenExpanded = !mNotificationParent.isGroupExpansionChanging()
+ && mChildrenExpanded;
+ int parentHeight = parentState.height;
for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i);
if (!firstChild) {
if (mUserLocked) {
- yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight,
- expandFactor);
+ yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight,
+ expandFactor);
} else {
yPosition += mChildrenExpanded ? mDividerHeight : mChildPadding;
}
@@ -383,11 +446,28 @@
}
firstChild = false;
}
+
StackViewState childState = resultState.getViewStateForView(child);
int intrinsicHeight = child.getIntrinsicHeight();
+ if (childrenExpanded) {
+ // When a group is expanded and moving into bottom stack, the bottom visible child
+ // adjusts its height to move into it. Children after it are hidden.
+ if (updateChildStateForExpandedGroup(child, parentHeight, childState, yPosition)) {
+ // Clipping might be deactivated if the view is transforming, however, clipping
+ // the child into the bottom stack should take precedent over this.
+ childState.isBottomClipped = true;
+ }
+ } else {
+ childState.hidden = false;
+ childState.height = intrinsicHeight;
+ childState.isBottomClipped = false;
+ }
childState.yTranslation = yPosition;
- childState.zTranslation = 0;
- childState.height = intrinsicHeight;
+ // When the group is expanded, the children cast the shadows rather than the parent
+ // so use the parent's elevation here.
+ childState.zTranslation = childrenExpanded
+ ? mNotificationParent.getTranslationZ()
+ : 0;
childState.dimmed = parentState.dimmed;
childState.dark = parentState.dark;
childState.hideSensitive = parentState.hideSensitive;
@@ -422,10 +502,44 @@
mGroupOverFlowState.alpha = mirrorView.getAlpha();
}
} else {
- mGroupOverFlowState.yTranslation += mNotificationHeaderHeight;
+ mGroupOverFlowState.yTranslation += mNotificationHeaderMargin;
mGroupOverFlowState.alpha = 0.0f;
}
}
+ if (mNotificationHeader != null) {
+ if (mHeaderViewState == null) {
+ mHeaderViewState = new ViewState();
+ }
+ mHeaderViewState.initFrom(mNotificationHeader);
+ mHeaderViewState.zTranslation = childrenExpanded
+ ? mNotificationParent.getTranslationZ()
+ : 0;
+ }
+ }
+
+ /**
+ * When moving into the bottom stack, the bottom visible child in an expanded group adjusts its
+ * height, children in the group after this are gone.
+ *
+ * @param child the child who's height to adjust.
+ * @param parentHeight the height of the parent.
+ * @param childState the state to update.
+ * @param yPosition the yPosition of the view.
+ * @return true if children after this one should be hidden.
+ */
+ private boolean updateChildStateForExpandedGroup(ExpandableNotificationRow child,
+ int parentHeight, StackViewState childState, int yPosition) {
+ final int top = yPosition + child.getClipTopAmount();
+ final int intrinsicHeight = child.getIntrinsicHeight();
+ final int bottom = top + intrinsicHeight;
+ int newHeight = intrinsicHeight;
+ if (bottom >= parentHeight) {
+ // Child is either clipped or gone
+ newHeight = Math.max((parentHeight - top), 0);
+ }
+ childState.hidden = newHeight == 0;
+ childState.height = newHeight;
+ return childState.height != intrinsicHeight && !childState.hidden;
}
private int getMaxAllowedVisibleChildren() {
@@ -450,6 +564,8 @@
if (mUserLocked) {
expandFraction = getGroupExpandFraction();
}
+ final boolean dividersVisible = mUserLocked
+ || mNotificationParent.isGroupExpansionChanging();
for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i);
StackViewState viewState = state.getViewStateForView(child);
@@ -464,6 +580,7 @@
alpha = NotificationUtils.interpolate(0, 0.5f,
Math.min(viewState.alpha, expandFraction));
}
+ tmpState.hidden = !dividersVisible;
tmpState.alpha = alpha;
state.applyViewState(divider, tmpState);
// There is no fake shadow to be drawn on the children
@@ -473,6 +590,9 @@
state.applyViewState(mOverflowNumber, mGroupOverFlowState);
mNeverAppliedGroupState = false;
}
+ if (mNotificationHeader != null) {
+ state.applyViewState(mNotificationHeader, mHeaderViewState);
+ }
}
/**
@@ -491,6 +611,8 @@
int childCount = mChildren.size();
ViewState tmpState = new ViewState();
float expandFraction = getGroupExpandFraction();
+ final boolean dividersVisible = mUserLocked
+ || mNotificationParent.isGroupExpansionChanging();
for (int i = childCount - 1; i >= 0; i--) {
ExpandableNotificationRow child = mChildren.get(i);
StackViewState viewState = state.getViewStateForView(child);
@@ -505,6 +627,7 @@
alpha = NotificationUtils.interpolate(0, 0.5f,
Math.min(viewState.alpha, expandFraction));
}
+ tmpState.hidden = !dividersVisible;
tmpState.alpha = alpha;
stateAnimator.startViewAnimations(divider, tmpState, baseDelay, duration);
// There is no fake shadow to be drawn on the children
@@ -521,6 +644,9 @@
stateAnimator.startViewAnimations(mOverflowNumber, mGroupOverFlowState,
baseDelay, duration);
}
+ if (mNotificationHeader != null) {
+ state.applyViewState(mNotificationHeader, mHeaderViewState);
+ }
}
public ExpandableNotificationRow getViewAtPosition(float y) {
@@ -541,14 +667,45 @@
public void setChildrenExpanded(boolean childrenExpanded) {
mChildrenExpanded = childrenExpanded;
updateExpansionStates();
+ if (mNotificationHeader != null) {
+ mNotificationHeader.setExpanded(childrenExpanded);
+ }
}
public void setNotificationParent(ExpandableNotificationRow parent) {
mNotificationParent = parent;
+ mHeaderUtil = new NotificationHeaderUtil(mNotificationParent);
+ }
+
+ public NotificationHeaderView getHeaderView() {
+ return mNotificationHeader;
+ }
+
+ public void updateHeaderVisibility(int visiblity) {
+ if (mNotificationHeader != null) {
+ mNotificationHeader.setVisibility(visiblity);
+ }
+ }
+
+ /**
+ * Called when a groups expansion changes to adjust the background of the header view.
+ *
+ * @param expanded whether the group is expanded.
+ */
+ public void updateHeaderForExpansion(boolean expanded) {
+ if (mNotificationHeader != null) {
+ if (expanded) {
+ ColorDrawable cd = new ColorDrawable();
+ cd.setColor(mNotificationParent.calculateBgColor());
+ mNotificationHeader.setHeaderBackgroundDrawable(cd);
+ } else {
+ mNotificationHeader.setHeaderBackgroundDrawable(null);
+ }
+ }
}
public int getMaxContentHeight() {
- int maxContentHeight = mNotificationHeaderHeight + mNotificatonTopPadding;
+ int maxContentHeight = mNotificationHeaderMargin + mNotificatonTopPadding;
int visibleChildren = 0;
int childCount = mChildren.size();
for (int i = 0; i < childCount; i++) {
@@ -601,7 +758,7 @@
}
private int getVisibleChildrenExpandHeight() {
- int intrinsicHeight = mNotificationHeaderHeight + mNotificatonTopPadding + mDividerHeight;
+ int intrinsicHeight = mNotificationHeaderMargin + mNotificatonTopPadding + mDividerHeight;
int visibleChildren = 0;
int childCount = mChildren.size();
int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
@@ -628,7 +785,7 @@
}
private int getMinHeight(int maxAllowedVisibleChildren) {
- int minExpandHeight = mNotificationHeaderHeight;
+ int minExpandHeight = mNotificationHeaderMargin;
int visibleChildren = 0;
boolean firstChild = true;
int childCount = mChildren.size();
@@ -653,9 +810,13 @@
if (mOverflowNumber != null) {
mOverflowInvertHelper.setInverted(dark, fade, delay);
}
+ mNotificationHeaderWrapper.setDark(dark, fade, delay);
}
- public void reInflateViews() {
+ public void reInflateViews(OnClickListener listener, StatusBarNotification notification) {
+ removeView(mNotificationHeader);
+ mNotificationHeader = null;
+ recreateNotificationHeader(listener, notification);
initDimens();
for (int i = 0; i < mDividers.size(); i++) {
View prevDivider = mDividers.get(i);
@@ -685,4 +846,12 @@
mHybridGroupManager.setOverflowNumberColor(mOverflowNumber,
mNotificationParent.getNotificationColor());
}
+
+ public void setRemoved() {
+ int childCount = mChildren.size();
+ for (int i = 0; i < childCount; i++) {
+ ExpandableNotificationRow child = mChildren.get(i);
+ child.setRemoved();
+ }
+ }
}
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 f7a2d2b..cab2534 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -34,6 +34,7 @@
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
+import android.os.Bundle;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.FloatProperty;
@@ -47,6 +48,8 @@
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.OverScroller;
@@ -336,6 +339,7 @@
private boolean mFadingOut;
private boolean mParentFadingOut;
private boolean mGroupExpandedForMeasure;
+ private boolean mScrollable;
private View mForcedScroll;
private float mBackgroundFadeAmount = 1.0f;
private static final Property<NotificationStackScrollLayout, Float> BACKGROUND_FADE =
@@ -443,7 +447,6 @@
private void initView(Context context) {
mScroller = new OverScroller(getContext());
- setFocusable(true);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
setClipChildren(false);
final ViewConfiguration configuration = ViewConfiguration.get(context);
@@ -730,6 +733,7 @@
mQsContainer = qsContainer;
}
+ @Override
public void onChildDismissed(View v) {
ExpandableNotificationRow row = (ExpandableNotificationRow) v;
if (!row.isDismissed()) {
@@ -817,6 +821,7 @@
return true; // Don't fade out the notification
}
+ @Override
public void onBeginDrag(View v) {
mFalsingManager.onNotificatonStartDismissing();
setSwipingInProgress(true);
@@ -845,6 +850,7 @@
return false;
}
+ @Override
public void onDragCancelled(View v) {
mFalsingManager.onNotificatonStopDismissing();
setSwipingInProgress(false);
@@ -903,11 +909,13 @@
return closestChild;
}
+ @Override
public ExpandableView getChildAtRawPosition(float touchX, float touchY) {
getLocationOnScreen(mTempInt2);
return getChildAtPosition(touchX - mTempInt2[0], touchY - mTempInt2[1]);
}
+ @Override
public ExpandableView getChildAtPosition(float touchX, float touchY) {
// find the view under the pointer, accounting for GONE views
final int count = getChildCount();
@@ -944,19 +952,31 @@
return null;
}
+ @Override
public boolean canChildBeExpanded(View v) {
return v instanceof ExpandableNotificationRow
&& ((ExpandableNotificationRow) v).isExpandable()
&& (mIsExpanded || !((ExpandableNotificationRow) v).isPinned());
}
+ /* Only ever called as a consequence of an expansion gesture in the shade. */
+ @Override
public void setUserExpandedChild(View v, boolean userExpanded) {
if (v instanceof ExpandableNotificationRow) {
- ((ExpandableNotificationRow) v).setUserExpanded(userExpanded,
- true /* allowChildrenExpansion */);
+ ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+ row.setUserExpanded(userExpanded, true /* allowChildrenExpansion */);
+ row.onExpandedByGesture(userExpanded);
}
}
+ @Override
+ public void setExpansionCancelled(View v) {
+ if (v instanceof ExpandableNotificationRow) {
+ ((ExpandableNotificationRow) v).setGroupExpansionChanging(false);
+ }
+ }
+
+ @Override
public void setUserLockedChild(View v, boolean userLocked) {
if (v instanceof ExpandableNotificationRow) {
((ExpandableNotificationRow) v).setUserLocked(userLocked);
@@ -1067,6 +1087,7 @@
return mScrollingEnabled;
}
+ @Override
public boolean canChildBeDismissed(View v) {
return StackScrollAlgorithm.canChildBeDismissed(v);
}
@@ -1728,6 +1749,15 @@
}
}
mContentHeight = height + mTopPadding;
+ updateScrollability();
+ }
+
+ private void updateScrollability() {
+ boolean scrollable = getScrollRange() > 0;
+ if (scrollable != mScrollable) {
+ mScrollable = scrollable;
+ setFocusable(scrollable);
+ }
}
private void updateBackground() {
@@ -1915,7 +1945,8 @@
// we're ending up at the same location as we are now, lets just skip the animation
bottom = finalBottom;
} else {
- bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight());
+ bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight()
+ - lastView.getExtraBottomPadding());
bottom = Math.min(bottom, getHeight());
}
} else {
@@ -2482,9 +2513,9 @@
mNeedsAnimation = false;
}
if (!mAnimationEvents.isEmpty() || isCurrentlyAnimating()) {
+ setAnimationRunning(true);
mStateAnimator.startAnimationForEvents(mAnimationEvents, mCurrentStackScrollState,
mGoToFullShadeDelay);
- setAnimationRunning(true);
mAnimationEvents.clear();
updateBackground();
updateViewShadows();
@@ -2929,16 +2960,6 @@
if (changed) {
if (!mIsExpanded) {
mGroupManager.collapseAllGroups();
- } else {
- // XXX: HACK: we should not be clearing notification effects from way down here.
- // But at the moment we don't have a reliable way to know when the window is
- // actually exposed to the air, so
- if (mPhoneStatusBar.getBarState() != StatusBarState.KEYGUARD) {
- if (DEBUG) {
- Log.v(TAG, "clearing notification effects from scroller");
- }
- mPhoneStatusBar.clearNotificationEffects();
- }
}
updateNotificationAnimationStates();
updateChronometers();
@@ -3112,6 +3133,7 @@
mListener.onChildLocationsChanged(this);
}
runAnimationFinishedRunnables();
+ setAnimationRunning(false);
updateBackground();
updateViewShadows();
}
@@ -3141,8 +3163,9 @@
expandableView.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
} else {
float yLocation = previous.getTranslationY() + previous.getActualHeight() -
- expandableView.getTranslationY();
- expandableView.setFakeShadowIntensity(diff / FakeShadowView.SHADOW_SIBLING_TRESHOLD,
+ expandableView.getTranslationY() - previous.getExtraBottomPadding();
+ expandableView.setFakeShadowIntensity(
+ diff / FakeShadowView.SHADOW_SIBLING_TRESHOLD,
previous.getOutlineAlpha(), (int) yLocation,
previous.getOutlineTranslation());
}
@@ -3227,6 +3250,7 @@
maxLength = Math.max(mDarkAnimationOriginIndex,
getNotGoneChildCount() - mDarkAnimationOriginIndex - 1);
}
+ maxLength = Math.max(0, maxLength);
long delay = maxLength * StackStateAnimator.ANIMATION_DELAY_PER_ELEMENT_DARK;
fadeAnimator.setStartDelay(delay);
fadeAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
@@ -3513,6 +3537,12 @@
if (!mGroupExpandedForMeasure) {
onHeightChanged(changedRow, false /* needsAnimation */);
}
+ runAfterAnimationFinished(new Runnable() {
+ @Override
+ public void run() {
+ changedRow.onFinishedExpansionChange();
+ }
+ });
}
@Override
@@ -3520,6 +3550,68 @@
mPhoneStatusBar.requestNotificationUpdate();
}
+ /** @hide */
+ @Override
+ public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEventInternal(event);
+ event.setScrollable(mScrollable);
+ event.setScrollX(mScrollX);
+ event.setScrollY(mOwnScrollY);
+ event.setMaxScrollX(mScrollX);
+ event.setMaxScrollY(getScrollRange());
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfoInternal(info);
+ final int scrollRange = getScrollRange();
+ if (scrollRange > 0) {
+ info.setScrollable(true);
+ if (mScrollY > 0) {
+ info.addAction(
+ AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_UP);
+ }
+ if (mScrollY < scrollRange) {
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_DOWN);
+ }
+ }
+ }
+
+ /** @hide */
+ @Override
+ public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
+ if (super.performAccessibilityActionInternal(action, arguments)) {
+ return true;
+ }
+ if (!isEnabled()) {
+ return false;
+ }
+ int direction = -1;
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
+ // fall through
+ case android.R.id.accessibilityActionScrollDown:
+ direction = 1;
+ // fall through
+ case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
+ // fall through
+ case android.R.id.accessibilityActionScrollUp:
+ final int viewportHeight = getHeight() - mPaddingBottom - mTopPadding - mPaddingTop
+ - mBottomStackPeekSize - mBottomStackSlowDownHeight;
+ final int targetScrollY = Math.max(0,
+ Math.min(mOwnScrollY + direction * viewportHeight, getScrollRange()));
+ if (targetScrollY != mOwnScrollY) {
+ mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScrollY - mOwnScrollY);
+ postInvalidateOnAnimation();
+ return true;
+ }
+ break;
+ }
+ return false;
+ }
+
@Override
public void onGroupsChanged() {
mPhoneStatusBar.requestNotificationUpdate();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index 1ccc908..8f0cd8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -26,9 +26,8 @@
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
+import java.util.WeakHashMap;
/**
* A state of a {@link com.android.systemui.statusbar.stack.NotificationStackScrollLayout} which
@@ -39,12 +38,12 @@
private static final String CHILD_NOT_FOUND_TAG = "StackScrollStateNoSuchChild";
private final ViewGroup mHostView;
- private Map<ExpandableView, StackViewState> mStateMap;
+ private WeakHashMap<ExpandableView, StackViewState> mStateMap;
private final int mClearAllTopPadding;
public StackScrollState(ViewGroup hostView) {
mHostView = hostView;
- mStateMap = new HashMap<ExpandableView, StackViewState>();
+ mStateMap = new WeakHashMap<>();
mClearAllTopPadding = hostView.getContext().getResources().getDimensionPixelSize(
R.dimen.clear_all_padding_top);
}
@@ -173,6 +172,9 @@
}
if (view instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+ if (state.isBottomClipped) {
+ row.setClipToActualHeight(true);
+ }
row.applyChildrenState(this);
}
return true;
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 6f451ff..0f94227 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -223,7 +223,7 @@
startViewAnimations(child, viewState, delay, duration);
// start height animation
- if (heightChanging && child.getActualHeight() != 0) {
+ if (heightChanging) {
startHeightAnimation(child, viewState, duration, delay);
}
@@ -270,7 +270,8 @@
public void startViewAnimations(View child, ViewState viewState, long delay, long duration) {
boolean wasVisible = child.getVisibility() == View.VISIBLE;
final float alpha = viewState.alpha;
- if (!wasVisible && alpha != 0 && !viewState.gone && !viewState.hidden) {
+ if (!wasVisible && (alpha != 0 || child.getAlpha() != 0)
+ && !viewState.gone && !viewState.hidden) {
child.setVisibility(View.VISIBLE);
}
boolean yTranslationChanging = child.getTranslationY() != viewState.yTranslation;
@@ -477,11 +478,27 @@
animator.addListener(getGlobalAnimationFinishedListener());
// remove the tag when the animation is finished
animator.addListener(new AnimatorListenerAdapter() {
+ boolean mWasCancelled;
+
@Override
public void onAnimationEnd(Animator animation) {
child.setTag(TAG_ANIMATOR_HEIGHT, null);
child.setTag(TAG_START_HEIGHT, null);
child.setTag(TAG_END_HEIGHT, null);
+ if (!mWasCancelled && child instanceof ExpandableNotificationRow) {
+ ((ExpandableNotificationRow) child).setGroupExpansionChanging(
+ false /* isExpansionChanging */);
+ }
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mWasCancelled = false;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mWasCancelled = true;
}
});
startAnimator(animator);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackViewState.java
index 1114e03..ecdee4e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackViewState.java
@@ -57,6 +57,11 @@
*/
public int location;
+ /**
+ * Whether a child in a group is being clipped at the bottom.
+ */
+ public boolean isBottomClipped;
+
@Override
public void copyFrom(ViewState viewState) {
super.copyFrom(viewState);
@@ -71,6 +76,7 @@
clipTopAmount = svs.clipTopAmount;
notGoneIndex = svs.notGoneIndex;
location = svs.location;
+ isBottomClipped = svs.isBottomClipped;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java
index bcf2f67..80c593c 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java
@@ -21,12 +21,11 @@
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View.OnFocusChangeListener;
import android.view.View;
import android.widget.ImageView;
-import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
import android.widget.TextView;
import com.android.systemui.R;
@@ -34,31 +33,28 @@
/**
* A view containing PIP controls including fullscreen, close, and media controls.
*/
-public class PipControlButtonView extends LinearLayout {
+public class PipControlButtonView extends RelativeLayout {
private OnFocusChangeListener mFocusChangeListener;
- private ImageView mButtonImageView;
+ private ImageView mIconImageView;
+ ImageView mButtonImageView;
private TextView mDescriptionTextView;
- private Animator mFocusGainAnimator;
- private Animator mFocusLoseAnimator;
+ private Animator mTextFocusGainAnimator;
+ private Animator mButtonFocusGainAnimator;
+ private Animator mTextFocusLossAnimator;
+ private Animator mButtonFocusLossAnimator;
private final OnFocusChangeListener mInternalFocusChangeListener =
new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
- if (mFocusLoseAnimator.isStarted()) {
- mFocusLoseAnimator.cancel();
- }
- mFocusGainAnimator.start();
+ startFocusGainAnimation();
} else {
- if (mFocusGainAnimator.isStarted()) {
- mFocusGainAnimator.cancel();
- }
- mFocusLoseAnimator.start();
+ startFocusLossAnimation();
}
if (mFocusChangeListener != null) {
- mFocusChangeListener.onFocusChange(v, hasFocus);
+ mFocusChangeListener.onFocusChange(PipControlButtonView.this, hasFocus);
}
}
};
@@ -82,9 +78,7 @@
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.tv_pip_control_button, this);
- setOrientation(LinearLayout.VERTICAL);
- setGravity(Gravity.CENTER);
-
+ mIconImageView = (ImageView) findViewById(R.id.icon);
mButtonImageView = (ImageView) findViewById(R.id.button);
mDescriptionTextView = (TextView) findViewById(R.id.desc);
@@ -103,12 +97,19 @@
super.onFinishInflate();
mButtonImageView.setOnFocusChangeListener(mInternalFocusChangeListener);
- mFocusGainAnimator = AnimatorInflater.loadAnimator(getContext(),
- R.anim.tv_pip_controls_text_focus_gain_animation);
- mFocusGainAnimator.setTarget(mDescriptionTextView);
- mFocusLoseAnimator = AnimatorInflater.loadAnimator(getContext(),
- R.anim.tv_pip_controls_text_focus_lose_animation);
- mFocusLoseAnimator.setTarget(mDescriptionTextView);
+ mTextFocusGainAnimator = AnimatorInflater.loadAnimator(getContext(),
+ R.anim.tv_pip_controls_focus_gain_animation);
+ mTextFocusGainAnimator.setTarget(mDescriptionTextView);
+ mButtonFocusGainAnimator = AnimatorInflater.loadAnimator(getContext(),
+ R.anim.tv_pip_controls_focus_gain_animation);
+ mButtonFocusGainAnimator.setTarget(mButtonImageView);
+
+ mTextFocusLossAnimator = AnimatorInflater.loadAnimator(getContext(),
+ R.anim.tv_pip_controls_focus_loss_animation);
+ mTextFocusLossAnimator.setTarget(mDescriptionTextView);
+ mButtonFocusLossAnimator = AnimatorInflater.loadAnimator(getContext(),
+ R.anim.tv_pip_controls_focus_loss_animation);
+ mButtonFocusLossAnimator.setTarget(mButtonImageView);
}
@Override
@@ -125,7 +126,7 @@
* Sets the drawable for the button with the given resource id.
*/
public void setImageResource(int resId) {
- mButtonImageView.setImageResource(resId);
+ mIconImageView.setImageResource(resId);
}
/**
@@ -136,8 +137,51 @@
mDescriptionTextView.setText(resId);
}
- @Override
- public boolean isFocused() {
- return mButtonImageView.isFocused();
+ private static void cancelAnimator(Animator animator) {
+ if (animator.isStarted()) {
+ animator.cancel();
+ }
+ }
+
+ /**
+ * Starts the focus gain animation.
+ */
+ public void startFocusGainAnimation() {
+ cancelAnimator(mButtonFocusLossAnimator);
+ cancelAnimator(mTextFocusLossAnimator);
+ mTextFocusGainAnimator.start();
+ if (mButtonImageView.getAlpha() < 1f) {
+ // If we had faded out the ripple drawable, run our manual focus change animation.
+ // See the comment at {@link #startFocusLossAnimation()} for the reason of manual
+ // animator.
+ mButtonFocusGainAnimator.start();
+ }
+ }
+
+ /**
+ * Starts the focus loss animation.
+ */
+ public void startFocusLossAnimation() {
+ cancelAnimator(mButtonFocusGainAnimator);
+ cancelAnimator(mTextFocusGainAnimator);
+ mTextFocusLossAnimator.start();
+ if (mButtonImageView.hasFocus()) {
+ // Button uses ripple that has the default animation for the focus changes.
+ // Howevever, it doesn't expose the API to fade out while it is focused,
+ // so we should manually run the fade out animation when PIP controls row loses focus.
+ mButtonFocusLossAnimator.start();
+ }
+ }
+
+ /**
+ * Resets to initial state.
+ */
+ public void reset() {
+ cancelAnimator(mButtonFocusGainAnimator);
+ cancelAnimator(mTextFocusGainAnimator);
+ cancelAnimator(mButtonFocusLossAnimator);
+ cancelAnimator(mTextFocusLossAnimator);
+ mButtonImageView.setAlpha(1f);
+ mDescriptionTextView.setAlpha(mButtonImageView.hasFocus() ? 1f : 0f);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java
index 5614bf9..71740ce 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java
@@ -61,8 +61,7 @@
private PipControlButtonView mCloseButtonView;
private PipControlButtonView mPlayPauseButtonView;
- private boolean mHasFocus;
- private OnFocusChangeListener mOnChildFocusChangeListener;
+ private PipControlButtonView mFocusedChild;
private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
@Override
@@ -80,8 +79,12 @@
private final OnFocusChangeListener mFocusChangeListener = new OnFocusChangeListener() {
@Override
- public void onFocusChange(View v, boolean hasFocus) {
- onChildViewFocusChanged();
+ public void onFocusChange(View view, boolean hasFocus) {
+ if (hasFocus) {
+ mFocusedChild = (PipControlButtonView) view;
+ } else if (mFocusedChild == view) {
+ mFocusedChild = null;
+ }
}
};
@@ -200,23 +203,13 @@
}
/**
- * Sets a listener to be invoked when {@link android.view.View.hasFocus()} is changed.
+ * Resets to initial state.
*/
- public void setOnChildFocusChangeListener(OnFocusChangeListener listener) {
- mOnChildFocusChangeListener = listener;
- }
-
- private void onChildViewFocusChanged() {
- // At this moment, hasFocus() returns true although there's no focused child.
- boolean hasFocus = (mFullButtonView != null && mFullButtonView.isFocused())
- || (mPlayPauseButtonView != null && mPlayPauseButtonView.isFocused())
- || (mCloseButtonView != null && mCloseButtonView.isFocused());
- if (mHasFocus != hasFocus) {
- mHasFocus = hasFocus;
- if (mOnChildFocusChangeListener != null) {
- mOnChildFocusChangeListener.onFocusChange(getFocusedChild(), mHasFocus);
- }
- }
+ public void reset() {
+ mFullButtonView.reset();
+ mCloseButtonView.reset();
+ mPlayPauseButtonView.reset();
+ mFullButtonView.requestFocus();
}
/**
@@ -225,4 +218,11 @@
public void setListener(Listener listener) {
mListener = listener;
}
+
+ /**
+ * Returns the focused control button view to animate focused button.
+ */
+ PipControlButtonView getFocusedButton() {
+ return mFocusedChild;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
index 476598d..30622d2 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -126,7 +126,6 @@
private int mSuspendPipResizingReason;
private Context mContext;
- private SystemServicesProxy mSystemServiceProxy;
private PipRecentsOverlayManager mPipRecentsOverlayManager;
private IActivityManager mActivityManager;
private MediaSessionManager mMediaSessionManager;
@@ -213,8 +212,7 @@
mPipBounds = mDefaultPipBounds;
mActivityManager = ActivityManagerNative.getDefault();
- mSystemServiceProxy = SystemServicesProxy.getInstance(context);
- mSystemServiceProxy.registerTaskStackListener(mTaskStackListener);
+ SystemServicesProxy.getInstance(context).registerTaskStackListener(mTaskStackListener);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_MEDIA_RESOURCE_GRANTED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter);
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java
index df44dc1..ffe96af 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java
@@ -48,12 +48,12 @@
abstract void onBackPressed();
}
- final PipManager mPipManager = PipManager.getInstance();
+ private final PipManager mPipManager = PipManager.getInstance();
private Listener mListener;
private PipControlsView mPipControlsView;
private View mScrim;
private Animator mFocusGainAnimator;
- private AnimatorSet mFocusLoseAnimatorSet;
+ private AnimatorSet mFocusLossAnimatorSet;
public PipRecentsControlsView(Context context) {
this(context, null, 0, 0);
@@ -80,12 +80,12 @@
mScrim = findViewById(R.id.scrim);
mFocusGainAnimator = loadAnimator(mPipControlsView,
- R.anim.tv_pip_controls_in_recents_focus_gain_animation);
+ R.anim.tv_pip_controls_in_recents_focus_gain_animation);
- mFocusLoseAnimatorSet = new AnimatorSet();
- mFocusLoseAnimatorSet.playSequentially(
+ mFocusLossAnimatorSet = new AnimatorSet();
+ mFocusLossAnimatorSet.playSequentially(
loadAnimator(mPipControlsView,
- R.anim.tv_pip_controls_in_recents_focus_lose_animation),
+ R.anim.tv_pip_controls_in_recents_focus_loss_animation),
loadAnimator(mScrim, R.anim.tv_pip_controls_in_recents_scrim_fade_in_animation));
Rect pipBounds = mPipManager.getRecentsFocusedPipBounds();
@@ -99,21 +99,29 @@
}
/**
- * Starts focus gaining animation.
+ * Starts focus gain animation.
*/
public void startFocusGainAnimation() {
// Hides the scrim view as soon as possible, before the PIP resize animation starts.
// If we don't, PIP will be moved down a bit and a gap between the scrim and PIP will be
// shown at the bottom of the PIP.
mScrim.setAlpha(0);
- startAnimator(mFocusGainAnimator, mFocusLoseAnimatorSet);
+ PipControlButtonView focus = mPipControlsView.getFocusedButton();
+ if (focus != null) {
+ focus.startFocusGainAnimation();
+ }
+ startAnimator(mFocusGainAnimator, mFocusLossAnimatorSet);
}
/**
- * Starts focus losing animation.
+ * Starts focus loss animation.
*/
- public void startFocusLoseAnimation() {
- startAnimator(mFocusLoseAnimatorSet, mFocusGainAnimator);
+ public void startFocusLossAnimation() {
+ PipControlButtonView focus = mPipControlsView.getFocusedButton();
+ if (focus != null) {
+ focus.startFocusLossAnimation();
+ }
+ startAnimator(mFocusLossAnimatorSet, mFocusGainAnimator);
}
/**
@@ -121,14 +129,14 @@
*/
public void reset() {
cancelAnimator(mFocusGainAnimator);
- cancelAnimator(mFocusLoseAnimatorSet);
+ cancelAnimator(mFocusLossAnimatorSet);
// Reset to initial state (i.e. end of focused)
- requestFocus();
+ mScrim.setAlpha(0);
mPipControlsView.setTranslationY(0);
mPipControlsView.setScaleX(1);
mPipControlsView.setScaleY(1);
- mScrim.setAlpha(0);
+ mPipControlsView.reset();
}
private static void startAnimator(Animator animator, Animator previousAnimator) {
@@ -153,13 +161,20 @@
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
- if (!event.isCanceled()
- && event.getKeyCode() == KeyEvent.KEYCODE_BACK
- && event.getAction() == KeyEvent.ACTION_UP) {
- if (mPipControlsView.mListener != null) {
- ((PipRecentsControlsView.Listener) mPipControlsView.mListener).onBackPressed();
+ if (!event.isCanceled()) {
+ if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
+ && event.getAction() == KeyEvent.ACTION_UP) {
+ if (mPipControlsView.mListener != null) {
+ ((PipRecentsControlsView.Listener) mPipControlsView.mListener).onBackPressed();
+ }
+ return true;
+ } else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) {
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ mPipManager.getPipRecentsOverlayManager().clearFocus();
+ }
+ // Consume the down event always to prevent warning logs from ViewRootImpl.
+ return true;
}
- return true;
}
return super.dispatchKeyEvent(event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
index 6e4a593..895b8a2 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
@@ -18,15 +18,20 @@
import android.content.Context;
import android.graphics.PixelFormat;
+import android.graphics.Rect;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.WindowManager.LayoutParams;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
import com.android.systemui.R;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import static android.view.Gravity.CENTER_HORIZONTAL;
+import static android.view.Gravity.TOP;
+import static android.view.View.MeasureSpec.UNSPECIFIED;
import static com.android.systemui.tv.pip.PipManager.STATE_PIP_OVERLAY;
import static com.android.systemui.tv.pip.PipManager.STATE_PIP_RECENTS;
import static com.android.systemui.tv.pip.PipManager.STATE_PIP_RECENTS_FOCUSED;
@@ -42,13 +47,16 @@
private final PipManager mPipManager = PipManager.getInstance();
private final WindowManager mWindowManager;
+ private final SystemServicesProxy mSystemServicesProxy;
private View mOverlayView;
private PipRecentsControlsView mPipControlsView;
private View mRecentsView;
+ private boolean mTalkBackEnabled;
- private final LayoutParams mPipRecentsControlsViewLayoutParams;
- private final LayoutParams mPipRecentsControlsViewFocusedLayoutParams;
+ private LayoutParams mPipRecentsControlsViewLayoutParams;
+ private LayoutParams mPipRecentsControlsViewFocusedLayoutParams;
+ private boolean mHasFocusableInRecents;
private boolean mIsPipRecentsOverlayShown;
private boolean mIsRecentsShown;
private boolean mIsPipFocusedInRecent;
@@ -72,18 +80,7 @@
PipRecentsOverlayManager(Context context) {
mWindowManager = (WindowManager) context.getSystemService(WindowManager.class);
-
- mPipRecentsControlsViewLayoutParams = new WindowManager.LayoutParams(
- LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
- LayoutParams.TYPE_SYSTEM_DIALOG,
- LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE,
- PixelFormat.TRANSLUCENT);
- mPipRecentsControlsViewFocusedLayoutParams = new WindowManager.LayoutParams(
- LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
- LayoutParams.TYPE_SYSTEM_DIALOG,
- 0,
- PixelFormat.TRANSLUCENT);
-
+ mSystemServicesProxy = SystemServicesProxy.getInstance(context);
initViews(context);
}
@@ -101,6 +98,20 @@
}
}
});
+
+ mOverlayView.measure(UNSPECIFIED, UNSPECIFIED);
+ mPipRecentsControlsViewLayoutParams = new WindowManager.LayoutParams(
+ mOverlayView.getMeasuredWidth(), mOverlayView.getMeasuredHeight(),
+ LayoutParams.TYPE_SYSTEM_DIALOG,
+ LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE,
+ PixelFormat.TRANSLUCENT);
+ mPipRecentsControlsViewLayoutParams.gravity = TOP | CENTER_HORIZONTAL;
+ mPipRecentsControlsViewFocusedLayoutParams = new WindowManager.LayoutParams(
+ mOverlayView.getMeasuredWidth(), mOverlayView.getMeasuredHeight(),
+ LayoutParams.TYPE_SYSTEM_DIALOG,
+ 0,
+ PixelFormat.TRANSLUCENT);
+ mPipRecentsControlsViewFocusedLayoutParams.gravity = TOP | CENTER_HORIZONTAL;
}
/**
@@ -111,9 +122,10 @@
if (mIsPipRecentsOverlayShown) {
return;
}
+ mTalkBackEnabled = mSystemServicesProxy.isTouchExplorationEnabled();
+ mRecentsView.setVisibility(mTalkBackEnabled ? View.VISIBLE : View.GONE);
mIsPipRecentsOverlayShown = true;
mIsPipFocusedInRecent = true;
- mPipControlsView.reset();
mWindowManager.addView(mOverlayView, mPipRecentsControlsViewFocusedLayoutParams);
}
@@ -126,50 +138,46 @@
return;
}
mWindowManager.removeView(mOverlayView);
+ // Resets the controls view when its removed.
+ // If not, changing focus in reset will be show animation when Recents is resumed.
+ mPipControlsView.reset();
mIsPipRecentsOverlayShown = false;
}
/**
* Request focus to the PIP Recents overlay.
- * Called when the PIP view in {@link com.android.systemui.recents.tv.RecentsTvActivity}
- * is focused.
* This should be called only by {@link com.android.systemui.recents.tv.RecentsTvActivity}.
- * @param allowRecentsFocusable {@code true} if Recents can have focus. (i.e. Has a recent task)
+ * @param hasFocusableInRecents {@code true} if Recents can have focus. (i.e. Has a recent task)
*/
- public void requestFocus(boolean allowRecentsFocusable) {
- mRecentsView.setVisibility(allowRecentsFocusable ? View.VISIBLE : View.GONE);
+ public void requestFocus(boolean hasFocusableInRecents) {
+ mHasFocusableInRecents = hasFocusableInRecents;
if (!mIsPipRecentsOverlayShown || !mIsRecentsShown || mIsPipFocusedInRecent
|| !mPipManager.isPipShown()) {
return;
}
mIsPipFocusedInRecent = true;
- mPipManager.resizePinnedStack(STATE_PIP_RECENTS_FOCUSED);
-
- mWindowManager.updateViewLayout(mOverlayView, mPipRecentsControlsViewFocusedLayoutParams);
- mPipControlsView.requestFocus();
- mPipControlsView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
mPipControlsView.startFocusGainAnimation();
+ mWindowManager.updateViewLayout(mOverlayView, mPipRecentsControlsViewFocusedLayoutParams);
+ mPipManager.resizePinnedStack(STATE_PIP_RECENTS_FOCUSED);
+ if (mTalkBackEnabled) {
+ mPipControlsView.requestFocus();
+ mPipControlsView.sendAccessibilityEvent(
+ AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ }
}
/**
* Request focus to the PIP Recents overlay.
- * Called when the PIP view in {@link com.android.systemui.recents.tv.RecentsTvActivity}
- * is focused.
- * This should be called only by {@link com.android.systemui.recents.tv.RecentsTvActivity}.
*/
public void clearFocus() {
if (!mIsPipRecentsOverlayShown || !mIsRecentsShown || !mIsPipFocusedInRecent
- || !mPipManager.isPipShown()) {
+ || !mPipManager.isPipShown() || !mHasFocusableInRecents) {
return;
}
- if (!mRecentsView.hasFocus()) {
- // Let mRecentsView's focus listener handle clearFocus().
- mRecentsView.requestFocus();
- }
mIsPipFocusedInRecent = false;
- mPipManager.resizePinnedStack(STATE_PIP_RECENTS);
+ mPipControlsView.startFocusLossAnimation();
mWindowManager.updateViewLayout(mOverlayView, mPipRecentsControlsViewLayoutParams);
- mPipControlsView.startFocusLoseAnimation();
+ mPipManager.resizePinnedStack(STATE_PIP_RECENTS);
if (mCallback != null) {
mCallback.onRecentsFocused();
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index 65b93c7..f2cd885 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -396,6 +396,7 @@
mSpTexts.add(row.header);
row.slider = (SeekBar) row.view.findViewById(R.id.volume_row_slider);
row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row));
+ row.anim = null;
// forward events above the slider into the slider
row.view.setOnTouchListener(new OnTouchListener() {
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
index f0ca441..badc31e 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
@@ -25,6 +25,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.os.UserManager;
import android.text.Html;
import android.text.Html.ImageGetter;
import android.util.Log;
@@ -55,6 +56,10 @@
finish();
return;
}
+ if (UserManager.get(this).hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
+ finish();
+ return;
+ }
View view = View.inflate(this, R.layout.confirm, null);
((TextView) view.findViewById(R.id.warning)).setText(
Html.fromHtml(getString(R.string.warning, getVpnLabel()),
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 46da957..a1487e3 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2206,6 +2206,18 @@
// Settings launched from expanded quick settings.
ACTION_QS_EXPANDED_SETTINGS_LAUNCH = 406;
+ // Notification expansion state toggled by the expand affordance.
+ ACTION_NOTIFICATION_EXPANDER = 407;
+
+ // Notification group expansion state toggled by the expand affordance.
+ ACTION_NOTIFICATION_GROUP_EXPANDER = 408;
+
+ // Notification expansion state toggled by the expand gesture.
+ ACTION_NOTIFICATION_GESTURE_EXPANDER = 409;
+
+ // Notification group expansion state toggled by the expand gesture.
+ ACTION_NOTIFICATION_GROUP_GESTURE_EXPANDER = 410;
+
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
}
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index 3cc991c..ecba245 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -648,7 +648,16 @@
* @param policyFlags The policy flags associated with the event.
*/
private void handleMotionEventStateDragging(MotionEvent event, int policyFlags) {
- final int pointerIdBits = (1 << mDraggingPointerId);
+ int pointerIdBits = 0;
+ // Clear the dragging pointer id if it's no longer valid.
+ if (event.findPointerIndex(mDraggingPointerId) == -1) {
+ Slog.e(LOG_TAG, "mDraggingPointerId doesn't match any pointers on current event. " +
+ "mDraggingPointerId: " + Integer.toString(mDraggingPointerId) +
+ ", Event: " + event);
+ mDraggingPointerId = INVALID_POINTER_ID;
+ } else {
+ pointerIdBits = (1 << mDraggingPointerId);
+ }
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
throw new IllegalStateException("Dragging state can be reached only if two "
@@ -664,6 +673,9 @@
sendDownForAllNotInjectedPointers(event, policyFlags);
} break;
case MotionEvent.ACTION_MOVE: {
+ if (mDraggingPointerId == INVALID_POINTER_ID) {
+ break;
+ }
switch (event.getPointerCount()) {
case 1: {
// do nothing
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
index 3f95427..de2c58c 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
@@ -44,4 +44,19 @@
mImpl.setSafeMode(isSafeMode());
}
}
+
+ @Override
+ public void onUnlockUser(int userHandle) {
+ mImpl.onUserUnlocked(userHandle);
+ }
+
+ @Override
+ public void onStopUser(int userHandle) {
+ mImpl.onUserStopped(userHandle);
+ }
+
+ @Override
+ public void onSwitchUser(int userHandle) {
+ mImpl.reloadWidgetsMaskedStateForGroup(userHandle);
+ }
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index ac2dda3..4e0ddd6 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -158,12 +158,6 @@
if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
onConfigurationChanged();
- } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
- onUserUnlocked(userId);
- } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
- onUserStopped(userId);
- } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
- reloadWidgetsMaskedStateForGroup(userId);
} else if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action)
|| Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action)) {
synchronized (mLock) {
@@ -281,13 +275,6 @@
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
sdFilter, null, null);
- IntentFilter userFilter = new IntentFilter();
- userFilter.addAction(Intent.ACTION_USER_UNLOCKED);
- userFilter.addAction(Intent.ACTION_USER_STOPPED);
- userFilter.addAction(Intent.ACTION_USER_SWITCHED);
- mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
- userFilter, null, null);
-
IntentFilter offModeFilter = new IntentFilter();
offModeFilter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
offModeFilter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
@@ -454,7 +441,7 @@
* due to user not being available and package suspension.
* userId must be the group parent.
*/
- private void reloadWidgetsMaskedStateForGroup(int userId) {
+ void reloadWidgetsMaskedStateForGroup(int userId) {
if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
return;
}
@@ -2525,7 +2512,7 @@
}
}
- private void onUserUnlocked(int userId) {
+ void onUserUnlocked(int userId) {
if (isProfileWithLockedParent(userId)) {
return;
}
@@ -3072,7 +3059,7 @@
return new AtomicFile(settingsFile);
}
- private void onUserStopped(int userId) {
+ void onUserStopped(int userId) {
synchronized (mLock) {
boolean crossProfileWidgetsChanged = false;
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 1ab8160..acc2ec3 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -146,6 +146,7 @@
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
@@ -4664,7 +4665,7 @@
// a standalone thread. The runner owns this half of the pipe, and closes
// it to indicate EOD to the other end.
class SinglePackageBackupPreflight implements BackupRestoreTask, FullBackupPreflight {
- final AtomicLong mResult = new AtomicLong();
+ final AtomicLong mResult = new AtomicLong(BackupTransport.AGENT_ERROR);
final CountDownLatch mLatch = new CountDownLatch(1);
final IBackupTransport mTransport;
@@ -4684,8 +4685,13 @@
}
agent.doMeasureFullBackup(token, mBackupManagerBinder);
- // now wait to get our result back
- mLatch.await();
+ // Now wait to get our result back. If this backstop timeout is reached without
+ // the latch being thrown, flow will continue as though a result or "normal"
+ // timeout had been produced. In case of a real backstop timeout, mResult
+ // will still contain the value it was constructed with, AGENT_ERROR, which
+ // intentionaly falls into the "just report failure" code.
+ mLatch.await(TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
+
long totalSize = mResult.get();
// If preflight timed out, mResult will contain error code as int.
if (totalSize < 0) {
@@ -4738,7 +4744,7 @@
@Override
public long getExpectedSizeOrErrorCode() {
try {
- mLatch.await();
+ mLatch.await(TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
return mResult.get();
} catch (InterruptedException e) {
return BackupTransport.NO_MORE_DATA;
@@ -4763,8 +4769,8 @@
mPreflight = new SinglePackageBackupPreflight(transport);
mPreflightLatch = new CountDownLatch(1);
mBackupLatch = new CountDownLatch(1);
- mPreflightResult = BackupTransport.TRANSPORT_OK;
- mBackupResult = BackupTransport.TRANSPORT_OK;
+ mPreflightResult = BackupTransport.AGENT_ERROR;
+ mBackupResult = BackupTransport.AGENT_ERROR;
}
@Override
@@ -4801,7 +4807,7 @@
// otherwise return negative error code.
long getPreflightResultBlocking() {
try {
- mPreflightLatch.await();
+ mPreflightLatch.await(TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
if (mPreflightResult == BackupTransport.TRANSPORT_OK) {
return mPreflight.getExpectedSizeOrErrorCode();
} else {
@@ -4814,7 +4820,7 @@
int getBackupResultBlocking() {
try {
- mBackupLatch.await();
+ mBackupLatch.await(TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
return mBackupResult;
} catch (InterruptedException e) {
return BackupTransport.AGENT_ERROR;
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index dab7d70..b5b0cd8 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -2180,8 +2180,9 @@
Preconditions.checkNotNull(token);
for (int i = 0; i < AppOpsManager._NUM_OP; i++) {
String restriction = AppOpsManager.opToRestriction(i);
- if (restriction != null && restrictions.getBoolean(restriction, false)) {
- setUserRestrictionNoCheck(i, true, token, userHandle, null);
+ if (restriction != null) {
+ setUserRestrictionNoCheck(i, restrictions.getBoolean(restriction, false), token,
+ userHandle, null);
}
}
}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index f30a126..1f88be5 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1457,14 +1457,17 @@
BluetoothAdapter.STATE_OFF);
sendBluetoothServiceDownCallback();
- mBluetoothLock.writeLock().lock();
- if (mBluetooth != null) {
- mBluetooth = null;
- // Unbind
- mContext.unbindService(mConnection);
+ try {
+ mBluetoothLock.writeLock().lock();
+ if (mBluetooth != null) {
+ mBluetooth = null;
+ // Unbind
+ mContext.unbindService(mConnection);
+ }
+ mBluetoothGatt = null;
+ } finally {
+ mBluetoothLock.writeLock().unlock();
}
- mBluetoothGatt = null;
- mBluetoothLock.writeLock().unlock();
SystemClock.sleep(100);
@@ -1765,14 +1768,17 @@
sendBluetoothServiceDownCallback();
- mBluetoothLock.writeLock().lock();
- if (mBluetooth != null) {
- mBluetooth = null;
- // Unbind
- mContext.unbindService(mConnection);
+ try {
+ mBluetoothLock.writeLock().lock();
+ if (mBluetooth != null) {
+ mBluetooth = null;
+ // Unbind
+ mContext.unbindService(mConnection);
+ }
+ mBluetoothGatt = null;
+ } finally {
+ mBluetoothLock.writeLock().unlock();
}
- mBluetoothGatt = null;
- mBluetoothLock.writeLock().unlock();
mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
mState = BluetoothAdapter.STATE_OFF;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 95a9781..5118b3f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2245,6 +2245,11 @@
final boolean wasDefault = isDefaultNetwork(nai);
if (wasDefault) {
mDefaultInetConditionPublished = 0;
+ // Log default network disconnection before required book-keeping.
+ // Let rematchAllNetworksAndRequests() below record a new default network event
+ // if there is a fallback. Taken together, the two form a X -> 0, 0 -> Y sequence
+ // whose timestamps tell how long it takes to recover a default network.
+ logDefaultNetworkEvent(null, nai);
}
notifyIfacesChangedForNetworkStats();
// TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
@@ -2278,10 +2283,6 @@
}
mLegacyTypeTracker.remove(nai, wasDefault);
rematchAllNetworksAndRequests(null, 0);
- if (wasDefault && getDefaultNetwork() == null) {
- // Log that we lost the default network and there is no replacement.
- logDefaultNetworkEvent(null, nai);
- }
if (nai.created) {
// Tell netd to clean up the configuration for this network
// (routing rules, DNS, etc).
@@ -3227,9 +3228,6 @@
@Override
public LegacyVpnInfo getLegacyVpnInfo(int userId) {
enforceCrossUserPermission(userId);
- if (mLockdownEnabled) {
- return null;
- }
synchronized(mVpns) {
return mVpns.get(userId).getLegacyVpnInfo();
@@ -4584,7 +4582,7 @@
teardownUnneededNetwork(oldNetwork);
}
- private void makeDefault(NetworkAgentInfo newNetwork, NetworkAgentInfo prevNetwork) {
+ private void makeDefault(NetworkAgentInfo newNetwork) {
if (DBG) log("Switching to new default network: " + newNetwork);
setupDataActivityTracking(newNetwork);
try {
@@ -4596,7 +4594,6 @@
handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
updateTcpBufferSizes(newNetwork);
setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
- logDefaultNetworkEvent(newNetwork, prevNetwork);
}
// Handles a network appearing or improving its score.
@@ -4747,7 +4744,9 @@
}
if (isNewDefault) {
// Notify system services that this network is up.
- makeDefault(newNetwork, oldDefaultNetwork);
+ makeDefault(newNetwork);
+ // Log 0 -> X and Y -> X default network transitions, where X is the new default.
+ logDefaultNetworkEvent(newNetwork, oldDefaultNetwork);
synchronized (ConnectivityService.this) {
// have a new default network, release the transition wakelock in
// a second if it's held. The second pause is to allow apps
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 69960c7..bb966f7 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -542,6 +542,8 @@
"mms_temp_app_whitelist_duration";
private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION =
"sms_temp_app_whitelist_duration";
+ private static final String KEY_NOTIFICATION_WHITELIST_DURATION =
+ "notification_whitelist_duration";
/**
* This is the time, after becoming inactive, that we go in to the first
@@ -752,6 +754,14 @@
*/
public long SMS_TEMP_APP_WHITELIST_DURATION;
+ /**
+ * Amount of time we would like to whitelist an app that is handling a
+ * {@link android.app.PendingIntent} triggered by a {@link android.app.Notification}.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_NOTIFICATION_WHITELIST_DURATION
+ */
+ public long NOTIFICATION_WHITELIST_DURATION;
+
private final ContentResolver mResolver;
private final boolean mHasWatch;
private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -842,6 +852,8 @@
KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
SMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
+ NOTIFICATION_WHITELIST_DURATION = mParser.getLong(
+ KEY_NOTIFICATION_WHITELIST_DURATION, 30 * 1000L);
}
}
@@ -945,6 +957,10 @@
pw.print(" "); pw.print(KEY_SMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw);
pw.println();
+
+ pw.print(" "); pw.print(KEY_NOTIFICATION_WHITELIST_DURATION); pw.print("=");
+ TimeUtils.formatDuration(NOTIFICATION_WHITELIST_DURATION, pw);
+ pw.println();
}
}
@@ -1252,6 +1268,10 @@
addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
}
+ public long getNotificationWhitelistDuration() {
+ return mConstants.NOTIFICATION_WHITELIST_DURATION;
+ }
+
public void setNetworkPolicyTempWhitelistCallback(Runnable callback) {
setNetworkPolicyTempWhitelistCallbackInternal(callback);
}
@@ -1632,7 +1652,7 @@
}
entry.first.value = timeNow + duration;
if (DEBUG) {
- Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist");
+ Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist. New entry: " + newEntry);
}
if (newEntry) {
// No pending timeout for the app id, post a delayed message
@@ -1665,12 +1685,18 @@
}
private void postTempActiveTimeoutMessage(int uid, long delay) {
+ if (DEBUG) {
+ Slog.d(TAG, "postTempActiveTimeoutMessage: uid=" + uid + ", delay=" + delay);
+ }
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, uid, 0),
delay);
}
void checkTempAppWhitelistTimeout(int uid) {
final long timeNow = SystemClock.elapsedRealtime();
+ if (DEBUG) {
+ Slog.d(TAG, "checkTempAppWhitelistTimeout: uid=" + uid + ", timeNow=" + timeNow);
+ }
synchronized (this) {
Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(uid);
if (entry == null) {
@@ -1694,6 +1720,9 @@
}
} else {
// Need more time
+ if (DEBUG) {
+ Slog.d(TAG, "Time to remove UID " + uid + ": " + entry.first.value);
+ }
postTempActiveTimeoutMessage(uid, entry.first.value - timeNow);
}
}
@@ -2514,6 +2543,8 @@
pw.println(" Print currently whitelisted apps.");
pw.println(" whitelist [package ...]");
pw.println(" Add (prefix with +) or remove (prefix with -) packages.");
+ pw.println(" tempwhitelist");
+ pw.println(" Print packages that are temporarily whitelisted.");
pw.println(" tempwhitelist [-u] [package ..]");
pw.println(" Temporarily place packages in whitelist for 10 seconds.");
}
@@ -2817,8 +2848,7 @@
pw.println("Failed: " + re);
}
} else {
- pw.println("At least one package name must be specified");
- return -1;
+ dumpTempWhitelistSchedule(pw, false);
}
} else {
return shell.handleDefaultCommands(cmd);
@@ -2943,20 +2973,8 @@
pw.println();
}
}
- size = mTempWhitelistAppIdEndTimes.size();
- if (size > 0) {
- pw.println(" Temp whitelist schedule:");
- final long timeNow = SystemClock.elapsedRealtime();
- for (int i = 0; i < size; i++) {
- pw.print(" UID=");
- pw.print(mTempWhitelistAppIdEndTimes.keyAt(i));
- pw.print(": ");
- Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i);
- TimeUtils.formatDuration(entry.first.value, timeNow, pw);
- pw.print(" - ");
- pw.println(entry.second);
- }
- }
+ dumpTempWhitelistSchedule(pw, true);
+
size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0;
if (size > 0) {
pw.println(" Temp whitelist app ids:");
@@ -2968,7 +2986,7 @@
}
pw.print(" mLightEnabled="); pw.print(mLightEnabled);
- pw.print(" mDeepEnabled="); pw.println(mDeepEnabled);
+ pw.print(" mDeepEnabled="); pw.println(mDeepEnabled);
pw.print(" mForceIdle="); pw.println(mForceIdle);
pw.print(" mMotionSensor="); pw.println(mMotionSensor);
pw.print(" mCurDisplay="); pw.println(mCurDisplay);
@@ -3040,4 +3058,26 @@
}
}
}
-}
+
+ void dumpTempWhitelistSchedule(PrintWriter pw, boolean printTitle) {
+ final int size = mTempWhitelistAppIdEndTimes.size();
+ if (size > 0) {
+ String prefix = "";
+ if (printTitle) {
+ pw.println(" Temp whitelist schedule:");
+ prefix = " ";
+ }
+ final long timeNow = SystemClock.elapsedRealtime();
+ for (int i = 0; i < size; i++) {
+ pw.print(prefix);
+ pw.print("UID=");
+ pw.print(mTempWhitelistAppIdEndTimes.keyAt(i));
+ pw.print(": ");
+ Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i);
+ TimeUtils.formatDuration(entry.first.value, timeNow, pw);
+ pw.print(" - ");
+ pw.println(entry.second);
+ }
+ }
+ }
+ }
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 727bf5c..5d8fe7c 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -159,6 +159,7 @@
static final int MSG_BIND_INPUT = 1010;
static final int MSG_SHOW_SOFT_INPUT = 1020;
static final int MSG_HIDE_SOFT_INPUT = 1030;
+ static final int MSG_HIDE_CURRENT_INPUT_METHOD = 1035;
static final int MSG_ATTACH_TOKEN = 1040;
static final int MSG_CREATE_SESSION = 1050;
@@ -2846,6 +2847,11 @@
}
args.recycle();
return true;
+ case MSG_HIDE_CURRENT_INPUT_METHOD:
+ synchronized (mMethodMap) {
+ hideCurrentInputLocked(0, null);
+ }
+ return true;
case MSG_ATTACH_TOKEN:
args = (SomeArgs)msg.obj;
try {
@@ -3880,6 +3886,12 @@
mHandler.sendMessage(mHandler.obtainMessage(MSG_SWITCH_IME,
forwardDirection ? 1 : 0, 0));
}
+
+ @Override
+ public void hideCurrentInputMethod() {
+ mHandler.removeMessages(MSG_HIDE_CURRENT_INPUT_METHOD);
+ mHandler.sendEmptyMessage(MSG_HIDE_CURRENT_INPUT_METHOD);
+ }
}
private static String imeWindowStatusToString(final int imeWindowVis) {
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 4477e8b..fb1021e 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -43,11 +43,14 @@
import android.database.sqlite.SQLiteDatabase;
import android.os.Binder;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
import android.os.IProgressListener;
import android.os.Parcel;
+import android.os.Process;
import android.os.RemoteException;
import android.os.storage.IMountService;
+import android.os.storage.StorageManager;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -111,13 +114,12 @@
private static final int FBE_ENCRYPTED_NOTIFICATION = 0;
private static final boolean DEBUG = false;
- private static final String PROFILE_KEY_NAME_ENCRYPT = "profile_key_name_encrypt_";
- private static final String PROFILE_KEY_NAME_DECRYPT = "profile_key_name_decrypt_";
private static final int PROFILE_KEY_IV_SIZE = 12;
private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
private final Object mSeparateChallengeLock = new Object();
private final Context mContext;
+ private final Handler mHandler;
private final LockSettingsStorage mStorage;
private final LockSettingsStrongAuth mStrongAuth;
private final SynchronizedStrongAuthTracker mStrongAuthTracker;
@@ -128,6 +130,14 @@
private NotificationManager mNotificationManager;
private UserManager mUserManager;
+ private final KeyStore mKeyStore = KeyStore.getInstance();
+
+ /**
+ * The UIDs that are used for system credential storage in keystore.
+ */
+ private static final int[] SYSTEM_CREDENTIAL_UIDS = {Process.WIFI_UID, Process.VPN_UID,
+ Process.ROOT_UID, Process.SYSTEM_UID};
+
static {
// Just launch the home screen, which happens anyway
ACTION_NULL = new Intent(Intent.ACTION_MAIN);
@@ -235,6 +245,11 @@
randomLockSeed = SecureRandom.getInstance("SHA1PRNG").generateSeed(40);
String newPassword = String.valueOf(HexEncoding.encode(randomLockSeed));
setLockPasswordInternal(newPassword, managedUserPassword, managedUserId);
+ // We store a private credential for the managed user that's unlocked by the primary
+ // account holder's credential. As such, the user will never be prompted to enter this
+ // password directly, so we always store a password.
+ setLong(LockPatternUtils.PASSWORD_TYPE_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, managedUserId);
tieProfileLockToParent(managedUserId, newPassword);
} catch (NoSuchAlgorithmException | RemoteException e) {
Slog.e(TAG, "Fail to tie managed profile", e);
@@ -244,6 +259,7 @@
public LockSettingsService(Context context) {
mContext = context;
+ mHandler = new Handler();
mStrongAuth = new LockSettingsStrongAuth(context);
// Open the database
@@ -340,6 +356,10 @@
private void showEncryptionNotification(UserHandle user, CharSequence title, CharSequence message,
CharSequence detail, PendingIntent intent) {
if (DEBUG) Slog.v(TAG, "showing encryption notification, user: " + user.getIdentifier());
+
+ // Suppress all notifications on non-FBE devices for now
+ if (!StorageManager.isFileEncryptedNativeOrEmulated()) return;
+
Notification notification = new Notification.Builder(mContext)
.setSmallIcon(com.android.internal.R.drawable.ic_user_secure)
.setWhen(0)
@@ -367,10 +387,20 @@
hideEncryptionNotification(new UserHandle(userId));
}
- public void onUnlockUser(int userId) {
+ public void onUnlockUser(final int userId) {
// Hide notification first, as tie managed profile lock takes time
hideEncryptionNotification(new UserHandle(userId));
- tieManagedProfileLockIfNecessary(userId, null);
+
+ if (mUserManager.getUserInfo(userId).isManagedProfile()) {
+ // As tieManagedProfileLockIfNecessary() may try to unlock user, we should not do it
+ // in onUnlockUser() synchronously, otherwise it may cause a deadlock
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ tieManagedProfileLockIfNecessary(userId, null);
+ }
+ });
+ }
// Now we have unlocked the parent user we should show notifications
// about any profiles that exist.
@@ -524,6 +554,30 @@
setString("migrated_lockscreen_disabled", "true", 0);
Slog.i(TAG, "Migrated lockscreen disabled flag");
}
+
+ final List<UserInfo> users = mUserManager.getUsers();
+ for (int i = 0; i < users.size(); i++) {
+ final UserInfo userInfo = users.get(i);
+ if (userInfo.isManagedProfile() && mStorage.hasChildProfileLock(userInfo.id)) {
+ // When managed profile has a unified lock, the password quality stored has 2
+ // possibilities only.
+ // 1). PASSWORD_QUALITY_UNSPECIFIED, which is upgraded from dp2, and we are
+ // going to set it back to PASSWORD_QUALITY_ALPHANUMERIC.
+ // 2). PASSWORD_QUALITY_ALPHANUMERIC, which is the actual password quality for
+ // unified lock.
+ final long quality = getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userInfo.id);
+ if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+ // Only possible when it's upgraded from nyc dp3
+ Slog.i(TAG, "Migrated tied profile lock type");
+ setLong(LockPatternUtils.PASSWORD_TYPE_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, userInfo.id);
+ } else if (quality != DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC) {
+ // It should not happen
+ Slog.e(TAG, "Invalid tied profile lock type: " + quality);
+ }
+ }
+ }
} catch (RemoteException re) {
Slog.e(TAG, "Unable to migrate old data", re);
}
@@ -675,7 +729,7 @@
NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException,
CertificateException, IOException {
- if (DEBUG) Slog.v(TAG, "Unlock keystore for child profile");
+ if (DEBUG) Slog.v(TAG, "Get child profile decrytped key");
byte[] storedData = mStorage.readChildProfileLock(userId);
if (storedData == null) {
throw new FileNotFoundException("Child profile lock file not found");
@@ -687,7 +741,7 @@
java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
SecretKey decryptionKey = (SecretKey) keyStore.getKey(
- PROFILE_KEY_NAME_DECRYPT + userId, null);
+ LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId, null);
Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
+ KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE);
@@ -734,12 +788,6 @@
}
};
- // Turn off quite mode if it's enabled, only managed profile can return true for now, it
- // will return false if it is not a managed profile.
- if (mUserManager.isQuietModeEnabled(new UserHandle(userId))) {
- mUserManager.setQuietModeEnabled(userId, false);
- }
-
try {
ActivityManagerNative.getDefault().unlockUser(userId, token, secret, listener);
} catch (RemoteException e) {
@@ -758,7 +806,6 @@
// Unlock managed profile with unified lock
if (pi.isManagedProfile()
&& !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id)
- && !pi.isQuietModeEnabled()
&& mStorage.hasChildProfileLock(pi.id)) {
unlockChildProfile(pi.id);
}
@@ -976,14 +1023,14 @@
java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
keyStore.setEntry(
- PROFILE_KEY_NAME_ENCRYPT + userId,
+ LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId,
new java.security.KeyStore.SecretKeyEntry(secretKey),
new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build());
keyStore.setEntry(
- PROFILE_KEY_NAME_DECRYPT + userId,
+ LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId,
new java.security.KeyStore.SecretKeyEntry(secretKey),
new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
@@ -994,7 +1041,7 @@
// Key imported, obtain a reference to it.
SecretKey keyStoreEncryptionKey = (SecretKey) keyStore.getKey(
- PROFILE_KEY_NAME_ENCRYPT + userId, null);
+ LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId, null);
// The original key can now be discarded.
Cipher cipher = Cipher.getInstance(
@@ -1102,6 +1149,49 @@
}
@Override
+ public void resetKeyStore(int userId) throws RemoteException {
+ if (DEBUG) Slog.v(TAG, "Reset keystore for user: " + userId);
+ int managedUserId = -1;
+ String managedUserDecryptedPassword = null;
+ final List<UserInfo> profiles = mUserManager.getProfiles(userId);
+ for (UserInfo pi : profiles) {
+ // Unlock managed profile with unified lock
+ if (pi.isManagedProfile()
+ && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id)
+ && mStorage.hasChildProfileLock(pi.id)) {
+ try {
+ if (managedUserId == -1) {
+ managedUserDecryptedPassword = getDecryptedPasswordForTiedProfile(pi.id);
+ managedUserId = pi.id;
+ } else {
+ // Should not happen
+ Slog.e(TAG, "More than one managed profile, uid1:" + managedUserId
+ + ", uid2:" + pi.id);
+ }
+ } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
+ | NoSuchAlgorithmException | NoSuchPaddingException
+ | InvalidAlgorithmParameterException | IllegalBlockSizeException
+ | BadPaddingException | CertificateException | IOException e) {
+ Slog.e(TAG, "Failed to decrypt child profile key", e);
+ }
+ }
+ }
+ try {
+ // Clear all the users credentials could have been installed in for this user.
+ for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) {
+ for (int uid : SYSTEM_CREDENTIAL_UIDS) {
+ mKeyStore.clearUid(UserHandle.getUid(profileId, uid));
+ }
+ }
+ } finally {
+ if (managedUserId != -1 && managedUserDecryptedPassword != null) {
+ if (DEBUG) Slog.v(TAG, "Restore tied profile lock");
+ tieProfileLockToParent(managedUserId, managedUserDecryptedPassword);
+ }
+ }
+ }
+
+ @Override
public VerifyCredentialResponse checkPattern(String pattern, int userId) throws RemoteException {
return doVerifyPattern(pattern, false, 0, userId);
}
@@ -1393,8 +1483,8 @@
try {
java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
- keyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + targetUserId);
- keyStore.deleteEntry(PROFILE_KEY_NAME_DECRYPT + targetUserId);
+ keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + targetUserId);
+ keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + targetUserId);
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException
| IOException e) {
// We have tried our best to remove all keys
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 95dee01..6a8c8b0 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -753,7 +753,7 @@
public void updateServiceConnectionActivitiesLocked(ProcessRecord clientProc) {
ArraySet<ProcessRecord> updatedProcesses = null;
- for (int i=0; i<clientProc.connections.size(); i++) {
+ for (int i = 0; i < clientProc.connections.size(); i++) {
final ConnectionRecord conn = clientProc.connections.valueAt(i);
final ProcessRecord proc = conn.binding.service.app;
if (proc == null || proc == clientProc) {
@@ -831,8 +831,9 @@
int clientLabel = 0;
PendingIntent clientIntent = null;
+ final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID;
- if (callerApp.info.uid == Process.SYSTEM_UID) {
+ if (isCallerSystem) {
// Hacky kind of thing -- allow system stuff to tell us
// what they are, so we can report this elsewhere for
// others to know why certain services are running.
@@ -854,6 +855,12 @@
"BIND_TREAT_LIKE_ACTIVITY");
}
+ if ((flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0 && !isCallerSystem) {
+ throw new SecurityException(
+ "Non-system caller " + caller + " (pid=" + Binder.getCallingPid()
+ + ") set BIND_ALLOW_WHITELIST_MANAGEMENT when binding service " + service);
+ }
+
final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
@@ -1124,6 +1131,11 @@
}
if (r.binding.service.app != null) {
+ if (r.binding.service.app.whitelistManager) {
+ // Must reset flag here because on computeOomAdjLocked() the service
+ // connection will be gone...
+ r.binding.service.app.whitelistManager = false;
+ }
// This could have made the service less important.
if ((r.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
r.binding.service.app.treatLikeActivity = true;
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index f2bf4f9..43bb5ee 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -90,6 +90,7 @@
static final boolean DEBUG_VISIBLE_BEHIND = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_USAGE_STATS = DEBUG_ALL || false;
static final boolean DEBUG_PERMISSIONS_REVIEW = DEBUG_ALL || false;
+ static final boolean DEBUG_WHITELISTS = DEBUG_ALL || false;
static final String POSTFIX_ADD_REMOVE = (APPEND_CATEGORY_NAME) ? "_AddRemove" : "";
static final String POSTFIX_APP = (APPEND_CATEGORY_NAME) ? "_App" : "";
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7a59703..ec54116 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -201,6 +201,7 @@
import android.service.voice.VoiceInteractionSession;
import android.text.format.DateUtils;
import android.text.format.Time;
+import android.text.style.SuggestionSpan;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
@@ -265,6 +266,7 @@
import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
+import static android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static android.content.pm.PackageManager.GET_PROVIDERS;
import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
@@ -319,6 +321,7 @@
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USAGE_STATS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBLE_BEHIND;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_WHITELISTS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BACKUP;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BROADCAST;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP;
@@ -1343,6 +1346,7 @@
boolean mSupportsMultiWindow;
boolean mSupportsFreeformWindowManagement;
boolean mSupportsPictureInPicture;
+ boolean mSupportsLeanbackOnly;
Rect mDefaultPinnedStackBounds;
IActivityController mController = null;
boolean mControllerIsAMonkey = false;
@@ -5418,9 +5422,32 @@
}
}
+ final int pkgUidF = pkgUid;
+ final int userIdF = userId;
+ final IPackageDataObserver localObserver = new IPackageDataObserver.Stub() {
+ @Override
+ public void onRemoveCompleted(String packageName, boolean succeeded)
+ throws RemoteException {
+ synchronized (ActivityManagerService.this) {
+ finishForceStopPackageLocked(packageName, pkgUidF);
+ }
+
+ final Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
+ Uri.fromParts("package", packageName, null));
+ intent.putExtra(Intent.EXTRA_UID, pkgUidF);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUidF));
+ broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
+ null, null, 0, null, null, null, null, false, false, userIdF);
+
+ if (observer != null) {
+ observer.onRemoveCompleted(packageName, succeeded);
+ }
+ }
+ };
+
try {
// Clear application user data
- pm.clearApplicationUserData(packageName, observer, userId);
+ pm.clearApplicationUserData(packageName, localObserver, userId);
synchronized(this) {
// Remove all permissions granted from/to this package
@@ -5432,12 +5459,6 @@
inm.removeAutomaticZenRules(packageName);
inm.setNotificationPolicyAccessGranted(packageName, false);
- Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
- Uri.fromParts("package", packageName, null));
- intent.putExtra(Intent.EXTRA_UID, pkgUid);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUid));
- broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
- null, null, 0, null, null, null, null, false, false, userId);
} catch (RemoteException e) {
}
} finally {
@@ -5622,6 +5643,7 @@
}
if (mUserController.isUserRunningLocked(user, 0)) {
forceStopPackageLocked(packageName, pkgUid, "from pid " + callingPid);
+ finishForceStopPackageLocked(packageName, pkgUid);
}
}
}
@@ -5813,6 +5835,9 @@
private void forceStopPackageLocked(final String packageName, int uid, String reason) {
forceStopPackageLocked(packageName, UserHandle.getAppId(uid), false,
false, true, false, false, UserHandle.getUserId(uid), reason);
+ }
+
+ private void finishForceStopPackageLocked(final String packageName, int uid) {
Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
Uri.fromParts("package", packageName, null));
if (!mProcessesReady) {
@@ -7111,6 +7136,41 @@
}
}
+ /**
+ * Whitelists {@code targetUid} to temporarily bypass Power Save mode.
+ *
+ * <p>{@code callerUid} must be allowed to request such whitelist by calling
+ * {@link #addTempPowerSaveWhitelistGrantorUid(int)}.
+ */
+ void tempWhitelistAppForPowerSave(int callerPid, int callerUid, int targetUid, long duration) {
+ if (DEBUG_WHITELISTS) {
+ Slog.d(TAG, "tempWhitelistAppForPowerSave(" + callerPid + ", " + callerUid + ", "
+ + targetUid + ", " + duration + ")");
+ }
+ synchronized (mPidsSelfLocked) {
+ final ProcessRecord pr = mPidsSelfLocked.get(callerPid);
+ if (pr == null) {
+ Slog.w(TAG, "tempWhitelistAppForPowerSave() no ProcessRecord for pid " + callerPid);
+ return;
+ }
+ if (!pr.whitelistManager) {
+ if (DEBUG_WHITELISTS) {
+ Slog.d(TAG, "tempWhitelistAppForPowerSave() for target " + targetUid + ": pid "
+ + callerPid + " is not allowed");
+ }
+ return;
+ }
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mLocalDeviceIdleController.addPowerSaveTempWhitelistAppDirect(targetUid, duration,
+ true, "pe from uid:" + callerUid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
@Override
public void cancelIntentSender(IIntentSender sender) {
if (!(sender instanceof PendingIntentRecord)) {
@@ -10169,6 +10229,7 @@
int N = providers.size();
app.pubProviders.ensureCapacity(N + app.pubProviders.size());
for (int i=0; i<N; i++) {
+ // TODO: keep logic in sync with installEncryptionUnawareProviders
ProviderInfo cpi =
(ProviderInfo)providers.get(i);
boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,
@@ -11149,12 +11210,18 @@
final PackageInfo pkgInfo = AppGlobals.getPackageManager()
.getPackageInfo(pkgName, matchFlags, userId);
if (pkgInfo != null && !ArrayUtils.isEmpty(pkgInfo.providers)) {
- for (ProviderInfo provInfo : pkgInfo.providers) {
- if (Objects.equals(provInfo.processName, app.processName)) {
- Log.v(TAG, "Installing " + provInfo);
- app.thread.scheduleInstallProvider(provInfo);
+ for (ProviderInfo pi : pkgInfo.providers) {
+ // TODO: keep in sync with generateApplicationProvidersLocked
+ final boolean processMatch = Objects.equals(pi.processName,
+ app.processName) || pi.multiprocess;
+ final boolean userMatch = isSingleton(pi.processName,
+ pi.applicationInfo, pi.name, pi.flags)
+ ? (app.userId == UserHandle.USER_SYSTEM) : true;
+ if (processMatch && userMatch) {
+ Log.v(TAG, "Installing " + pi);
+ app.thread.scheduleInstallProvider(pi);
} else {
- Log.v(TAG, "Skipping " + provInfo);
+ Log.v(TAG, "Skipping " + pi);
}
}
}
@@ -12784,6 +12851,9 @@
final boolean forceRtl = Settings.Global.getInt(resolver, DEVELOPMENT_FORCE_RTL, 0) != 0;
final boolean forceResizable = Settings.Global.getInt(
resolver, DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
+ final boolean supportsLeanbackOnly =
+ mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK_ONLY);
+
// Transfer any global setting for forcing RTL layout, into a System Property
SystemProperties.set(DEVELOPMENT_FORCE_RTL, forceRtl ? "1":"0");
@@ -12799,6 +12869,7 @@
mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
mAlwaysFinishActivities = alwaysFinishActivities;
mLenientBackgroundCheck = lenientBackgroundCheck;
+ mSupportsLeanbackOnly = supportsLeanbackOnly;
mForceResizableActivities = forceResizable;
mWindowManager.setForceResizableTasks(mForceResizableActivities);
if (supportsMultiWindow || forceResizable) {
@@ -16863,6 +16934,13 @@
return false;
}
+ // If the app is a regular app (uid >= 10000) and not the system server or phone
+ // process, etc, then mark it as being in full backup so that certain calls to the
+ // process can be blocked. This is not reset to false anywhere because we kill the
+ // process after the full backup is done and the ProcessRecord will vaporize anyway.
+ if (UserHandle.isApp(app.uid) && backupMode == IApplicationThread.BACKUP_MODE_FULL) {
+ proc.inFullBackup = true;
+ }
r.app = proc;
mBackupTarget = r;
mBackupAppName = app.packageName;
@@ -17390,15 +17468,24 @@
|| AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
|| AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)
|| LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION.equals(action)
- || TelephonyIntents.ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE.equals(action)) {
+ || TelephonyIntents.ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE.equals(action)
+ || SuggestionSpan.ACTION_SUGGESTION_PICKED.equals(action)) {
// Broadcast is either protected, or it's a public action that
// we've relaxed, so it's fine for system internals to send.
} else {
// The vast majority of broadcasts sent from system internals
// should be protected to avoid security holes, so yell loudly
// to ensure we examine these cases.
- Log.wtf(TAG, "Sending non-protected broadcast " + action
- + " from system", new Throwable());
+ if (callerApp != null) {
+ Log.wtf(TAG, "Sending non-protected broadcast " + action
+ + " from system " + callerApp.toShortString() + " pkg " + callerPackage,
+ new Throwable());
+ } else {
+ Log.wtf(TAG, "Sending non-protected broadcast " + action
+ + " from system uid " + UserHandle.formatUid(callingUid)
+ + " pkg " + callerPackage,
+ new Throwable());
+ }
}
} else {
@@ -17503,13 +17590,13 @@
final boolean killProcess =
!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false);
final boolean fullUninstall = removed && !replacing;
- if (killProcess) {
- forceStopPackageLocked(ssp, UserHandle.getAppId(
- intent.getIntExtra(Intent.EXTRA_UID, -1)),
- false, true, true, false, fullUninstall, userId,
- removed ? "pkg removed" : "pkg changed");
- }
if (removed) {
+ if (killProcess) {
+ forceStopPackageLocked(ssp, UserHandle.getAppId(
+ intent.getIntExtra(Intent.EXTRA_UID, -1)),
+ false, true, true, false, fullUninstall, userId,
+ removed ? "pkg removed" : "pkg changed");
+ }
final int cmd = killProcess
? IApplicationThread.PACKAGE_REMOVED
: IApplicationThread.PACKAGE_REMOVED_DONT_KILL;
@@ -17526,6 +17613,12 @@
mBatteryStatsService.notePackageUninstalled(ssp);
}
} else {
+ if (killProcess) {
+ killPackageProcessesLocked(ssp, UserHandle.getAppId(
+ intent.getIntExtra(Intent.EXTRA_UID, -1)),
+ userId, ProcessList.INVALID_ADJ,
+ false, true, true, false, "change " + ssp);
+ }
cleanupDisabledPackageComponentsLocked(ssp, userId, killProcess,
intent.getStringArrayExtra(
Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));
@@ -18283,8 +18376,8 @@
void updateUserConfigurationLocked() {
Configuration configuration = new Configuration(mConfiguration);
- Settings.System.getConfigurationForUser(mContext.getContentResolver(), configuration,
- mUserController.getCurrentUserIdLocked());
+ Settings.System.adjustConfigurationForUser(mContext.getContentResolver(), configuration,
+ mUserController.getCurrentUserIdLocked(), Settings.System.canWrite(mContext));
updateConfigurationLocked(configuration, null, false);
}
@@ -18325,21 +18418,21 @@
EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
if (!initLocale && !values.getLocales().isEmpty() && values.userSetLocale) {
- final Locale locale;
- if (values.getLocales().size() == 1) {
- // This is an optimization to avoid the JNI call when the result of
- // getFirstMatch() does not depend on the supported locales.
- locale = values.getLocales().get(0);
- } else {
+ final LocaleList locales = values.getLocales();
+ int bestLocaleIndex = 0;
+ if (locales.size() > 1) {
if (mSupportedSystemLocales == null) {
mSupportedSystemLocales =
Resources.getSystem().getAssets().getLocales();
}
- locale = values.getLocales().getFirstMatch(mSupportedSystemLocales);
+ bestLocaleIndex = Math.max(0,
+ locales.getFirstMatchIndex(mSupportedSystemLocales));
}
- SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
+ SystemProperties.set("persist.sys.locale",
+ locales.get(bestLocaleIndex).toLanguageTag());
+ LocaleList.setDefault(locales, bestLocaleIndex);
mHandler.sendMessage(mHandler.obtainMessage(SEND_LOCALE_TO_MOUNT_DAEMON_MSG,
- locale));
+ locales.get(bestLocaleIndex)));
}
mConfigurationSeq++;
@@ -18966,6 +19059,9 @@
}
}
}
+
+ app.whitelistManager = false;
+
for (int conni = s.connections.size()-1;
conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
@@ -18984,6 +19080,10 @@
// Binding to ourself is not interesting.
continue;
}
+ if ((cr.flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
+ app.whitelistManager = true;
+ }
+
if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
ProcessRecord client = cr.binding.client;
int clientAdj = computeOomAdjLocked(client, cachedAdj,
@@ -21255,6 +21355,15 @@
}
}
}
+
+ @Override
+ public void setPendingIntentWhitelistDuration(IIntentSender target, long duration) {
+ if (!(target instanceof PendingIntentRecord)) {
+ Slog.w(TAG, "markAsSentFromNotification(): not a PendingIntentRecord: " + target);
+ return;
+ }
+ ((PendingIntentRecord) target).setWhitelistDuration(duration);
+ }
}
private final class SleepTokenImpl extends SleepToken {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 8b637e0..ba044cc4 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1832,9 +1832,9 @@
boolean isVisible =
!behindFullscreenActivity || r.mLaunchTaskBehind || activityVisibleBehind;
- if (isVisible && r.isRecentsActivity()) {
- // Recents activity can only be visible if the home stack is the focused stack or we are
- // in split-screen mode.
+ if (mService.mSupportsLeanbackOnly && isVisible && r.isRecentsActivity()) {
+ // On devices that support leanback only (Android TV), Recents activity can only be
+ // visible if the home stack is the focused stack or we are in split-screen mode.
isVisible = mStackSupervisor.getStack(DOCKED_STACK_ID) != null
|| mStackSupervisor.isFocusedStack(this);
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 01b2eb4..197d9ec 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1338,7 +1338,9 @@
// Update any services we are bound to that might care about whether
// their client may have activities.
- mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
+ if (r.app != null) {
+ mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
+ }
return true;
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index dc4d7b1..7101937 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -558,7 +558,16 @@
startedActivityStackId = mTargetStack.mStackId;
}
- if (startedActivityStackId == DOCKED_STACK_ID && prevFocusedStackId == HOME_STACK_ID) {
+ // If we launched the activity from a no display activity that was launched from the home
+ // screen, we also need to start recents to un-minimize the docked stack, since the
+ // noDisplay activity will be finished shortly after.
+ // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
+ // visibility instead of using this flag.
+ final boolean noDisplayActivityOverHome = mSourceRecord != null
+ && mSourceRecord.noDisplay
+ && mSourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
+ if (startedActivityStackId == DOCKED_STACK_ID
+ && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
final ActivityRecord topActivityHomeStack = homeStack != null
? homeStack.topRunningActivityLocked() : null;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index b4df10f..def6828 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -88,6 +88,9 @@
*/
private static final long EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS = 2000;
+ // There is some accuracy error in wifi reports so allow some slop in the results.
+ private static final long MAX_WIFI_STATS_SAMPLE_ERROR_MILLIS = 750;
+
private static IBatteryStats sService;
final BatteryStatsImpl mStats;
@@ -1338,32 +1341,33 @@
} else {
final long totalActiveTimeMs = txTimeMs + rxTimeMs;
long maxExpectedIdleTimeMs;
- // Active time can never be greater than the total time, the stats received seem
- // to be corrupt.
if (totalActiveTimeMs > timePeriodMs) {
- maxExpectedIdleTimeMs = timePeriodMs;
- StringBuilder sb = new StringBuilder();
- sb.append("Total Active time ");
- TimeUtils.formatDuration(totalActiveTimeMs, sb);
- sb.append(" is longer than sample period ");
- TimeUtils.formatDuration(timePeriodMs, sb);
- sb.append(".\n");
- sb.append("Previous WiFi snapshot: ").append("idle=");
- TimeUtils.formatDuration(lastIdleMs, sb);
- sb.append(" rx=");
- TimeUtils.formatDuration(lastRxMs, sb);
- sb.append(" tx=");
- TimeUtils.formatDuration(lastTxMs, sb);
- sb.append(" e=").append(lastEnergy);
- sb.append("\n");
- sb.append("Current WiFi snapshot: ").append("idle=");
- TimeUtils.formatDuration(latest.mControllerIdleTimeMs, sb);
- sb.append(" rx=");
- TimeUtils.formatDuration(latest.mControllerRxTimeMs, sb);
- sb.append(" tx=");
- TimeUtils.formatDuration(latest.mControllerTxTimeMs, sb);
- sb.append(" e=").append(latest.mControllerEnergyUsed);
- Slog.wtf(TAG, sb.toString());
+ // Cap the max idle time at zero since the active time consumed the whole time
+ maxExpectedIdleTimeMs = 0;
+ if (totalActiveTimeMs > timePeriodMs + MAX_WIFI_STATS_SAMPLE_ERROR_MILLIS) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Total Active time ");
+ TimeUtils.formatDuration(totalActiveTimeMs, sb);
+ sb.append(" is longer than sample period ");
+ TimeUtils.formatDuration(timePeriodMs, sb);
+ sb.append(".\n");
+ sb.append("Previous WiFi snapshot: ").append("idle=");
+ TimeUtils.formatDuration(lastIdleMs, sb);
+ sb.append(" rx=");
+ TimeUtils.formatDuration(lastRxMs, sb);
+ sb.append(" tx=");
+ TimeUtils.formatDuration(lastTxMs, sb);
+ sb.append(" e=").append(lastEnergy);
+ sb.append("\n");
+ sb.append("Current WiFi snapshot: ").append("idle=");
+ TimeUtils.formatDuration(latest.mControllerIdleTimeMs, sb);
+ sb.append(" rx=");
+ TimeUtils.formatDuration(latest.mControllerRxTimeMs, sb);
+ sb.append(" tx=");
+ TimeUtils.formatDuration(latest.mControllerTxTimeMs, sb);
+ sb.append(" e=").append(latest.mControllerEnergyUsed);
+ Slog.wtf(TAG, sb.toString());
+ }
} else {
maxExpectedIdleTimeMs = timePeriodMs - totalActiveTimeMs;
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 0acc2a0..8ffc6f3 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -258,6 +258,11 @@
if (app.thread == null) {
throw new RemoteException();
}
+ if (app.inFullBackup) {
+ skipReceiverLocked(r);
+ return;
+ }
+
r.receiver = app.thread.asBinder();
r.curApp = app;
app.curReceiver = r;
@@ -341,13 +346,17 @@
}
if (r != null) {
- logBroadcastReceiverDiscardLocked(r);
- finishReceiverLocked(r, r.resultCode, r.resultData,
- r.resultExtras, r.resultAbort, false);
- scheduleBroadcastsLocked();
+ skipReceiverLocked(r);
}
}
+ private void skipReceiverLocked(BroadcastRecord r) {
+ logBroadcastReceiverDiscardLocked(r);
+ finishReceiverLocked(r, r.resultCode, r.resultData,
+ r.resultExtras, r.resultAbort, false);
+ scheduleBroadcastsLocked();
+ }
+
public void scheduleBroadcastsLocked() {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
+ mQueueName + "]: current="
@@ -641,9 +650,17 @@
try {
if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
"Delivering to " + filter + " : " + r);
- performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
- new Intent(r.intent), r.resultCode, r.resultData,
- r.resultExtras, r.ordered, r.initialSticky, r.userId);
+ if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
+ // Skip delivery if full backup in progress
+ // If it's an ordered broadcast, we need to continue to the next receiver.
+ if (ordered) {
+ skipReceiverLocked(r);
+ }
+ } else {
+ performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
+ new Intent(r.intent), r.resultCode, r.resultData,
+ r.resultExtras, r.ordered, r.initialSticky, r.userId);
+ }
if (ordered) {
r.state = BroadcastRecord.CALL_DONE_RECEIVE;
}
diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/services/core/java/com/android/server/am/LockTaskNotify.java
index afde322..8c18c46 100644
--- a/services/core/java/com/android/server/am/LockTaskNotify.java
+++ b/services/core/java/com/android/server/am/LockTaskNotify.java
@@ -21,7 +21,6 @@
import android.os.Handler;
import android.os.Message;
import android.view.WindowManager;
-import android.view.accessibility.AccessibilityManager;
import android.widget.Toast;
import com.android.internal.R;
@@ -35,13 +34,10 @@
private final Context mContext;
private final H mHandler;
- private AccessibilityManager mAccessibilityManager;
private Toast mLastToast;
public LockTaskNotify(Context context) {
mContext = context;
- mAccessibilityManager = (AccessibilityManager)
- mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
mHandler = new H();
}
@@ -54,8 +50,7 @@
if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_LOCKED) {
text = mContext.getString(R.string.lock_to_app_toast_locked);
} else if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_PINNED) {
- text = mContext.getString(mAccessibilityManager.isEnabled()
- ? R.string.lock_to_app_toast_accessible : R.string.lock_to_app_toast);
+ text = mContext.getString(R.string.lock_to_app_toast);
}
if (text == null) {
return;
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 1f8d26b..c1ff4dd 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -47,6 +47,7 @@
final WeakReference<PendingIntentRecord> ref;
boolean sent = false;
boolean canceled = false;
+ private long whitelistDuration = 0;
String stringName;
String lastTagPrefix;
@@ -66,9 +67,9 @@
final int flags;
final int hashCode;
final int userId;
-
+
private static final int ODD_PRIME_NUMBER = 37;
-
+
Key(int _t, String _p, ActivityRecord _a, String _w,
int _r, Intent[] _i, String[] _it, int _f, Bundle _o, int _userId) {
type = _t;
@@ -106,7 +107,7 @@
//Slog.i(ActivityManagerService.TAG, this + " hashCode=0x"
// + Integer.toHexString(hashCode));
}
-
+
public boolean equals(Object otherObj) {
if (otherObj == null) {
return false;
@@ -198,6 +199,11 @@
ref = new WeakReference<PendingIntentRecord>(this);
}
+ void setWhitelistDuration(long duration) {
+ this.whitelistDuration = duration;
+ this.stringName = null;
+ }
+
public void send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
String requiredPermission, Bundle options) {
sendInner(code, intent, resolvedType, finishedReceiver,
@@ -216,6 +222,14 @@
if (intent != null) intent.setDefusable(true);
if (options != null) options.setDefusable(true);
+ if (whitelistDuration > 0 && !canceled) {
+ // Must call before acquiring the lock. It's possible the method return before sending
+ // the intent due to some validations inside the lock, in which case the UID shouldn't
+ // be whitelisted, but since the whitelist is temporary, that would be ok.
+ owner.tempWhitelistAppForPowerSave(Binder.getCallingPid(), Binder.getCallingUid(), uid,
+ whitelistDuration);
+ }
+
synchronized (owner) {
final ActivityContainer activityContainer = (ActivityContainer)container;
if (activityContainer != null && activityContainer.mParentActivity != null &&
@@ -361,7 +375,7 @@
}
}
}
-
+
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("uid="); pw.print(uid);
pw.print(" packageName="); pw.print(key.packageName);
@@ -383,6 +397,7 @@
pw.print(prefix); pw.print("sent="); pw.print(sent);
pw.print(" canceled="); pw.println(canceled);
}
+ pw.print(prefix); pw.println("whitelistDuration="); pw.println(whitelistDuration);
}
public String toString() {
@@ -396,6 +411,9 @@
sb.append(key.packageName);
sb.append(' ');
sb.append(key.typeName());
+ if (whitelistDuration > 0) {
+ sb.append( " (whitelistDuration: ").append(whitelistDuration).append("ms)");
+ }
sb.append('}');
return stringName = sb.toString();
}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 059acbd..691fd2a 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -192,6 +192,11 @@
// app that installed the package.
ComponentName errorReportReceiver;
+ // Process is currently hosting a backup agent for backup or restore
+ public boolean inFullBackup;
+ // App is allowed to manage whitelists such as temporary Power Save mode whitelist.
+ boolean whitelistManager;
+
void dump(PrintWriter pw, String prefix) {
final long now = SystemClock.uptimeMillis();
@@ -373,6 +378,9 @@
}
pw.println();
}
+ if (whitelistManager) {
+ pw.print(prefix); pw.print("whitelistManager="); pw.println(whitelistManager);
+ }
if (activities.size() > 0) {
pw.print(prefix); pw.println("Activities:");
for (int i=0; i<activities.size(); i++) {
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 595d086..f6232fe 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -18,7 +18,6 @@
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
-import static android.app.ActivityManager.FLAG_AND_UNLOCKING_OR_UNLOCKED;
import static android.app.ActivityManager.USER_OP_ERROR_IS_SYSTEM;
import static android.app.ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP;
import static android.app.ActivityManager.USER_OP_IS_CURRENT;
@@ -233,6 +232,7 @@
// but we might immediately step into RUNNING below if the user
// storage is already unlocked.
if (uss.setState(STATE_BOOTING, STATE_RUNNING_LOCKED)) {
+ getUserManagerInternal().setUserState(userId, uss.state);
Intent intent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED, null);
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
@@ -276,7 +276,7 @@
if (!StorageManager.isUserKeyUnlocked(userId)) return;
if (uss.setState(STATE_RUNNING_LOCKED, STATE_RUNNING_UNLOCKING)) {
- getUserManagerInternal().setUserUnlockingOrUnlocked(userId, true);
+ getUserManagerInternal().setUserState(userId, uss.state);
uss.mUnlockProgress.start();
// Prepare app storage before we go any further
@@ -307,7 +307,7 @@
if (!StorageManager.isUserKeyUnlocked(userId)) return;
if (uss.setState(STATE_RUNNING_UNLOCKING, STATE_RUNNING_UNLOCKED)) {
- getUserManagerInternal().setUserUnlockingOrUnlocked(userId, true);
+ getUserManagerInternal().setUserState(userId, uss.state);
uss.mUnlockProgress.finish();
// Dispatch unlocked to external apps
@@ -481,7 +481,7 @@
if (uss.state != UserState.STATE_STOPPING
&& uss.state != UserState.STATE_SHUTDOWN) {
uss.setState(UserState.STATE_STOPPING);
- getUserManagerInternal().setUserUnlockingOrUnlocked(userId, false);
+ getUserManagerInternal().setUserState(userId, uss.state);
updateStartedUserArrayLocked();
long ident = Binder.clearCallingIdentity();
@@ -543,7 +543,7 @@
}
uss.setState(UserState.STATE_SHUTDOWN);
}
- getUserManagerInternal().setUserUnlockingOrUnlocked(userId, false);
+ getUserManagerInternal().setUserState(userId, uss.state);
mService.mBatteryStatsService.noteEvent(
BatteryStats.HistoryItem.EVENT_USER_RUNNING_FINISH,
@@ -572,6 +572,7 @@
stopped = true;
// User can no longer run.
mStartedUsers.remove(userId);
+ getUserManagerInternal().removeUserState(userId);
mUserLru.remove(Integer.valueOf(userId));
updateStartedUserArrayLocked();
@@ -779,7 +780,9 @@
// If the user we are switching to is not currently started, then
// we need to start it now.
if (mStartedUsers.get(userId) == null) {
- mStartedUsers.put(userId, new UserState(UserHandle.of(userId)));
+ UserState userState = new UserState(UserHandle.of(userId));
+ mStartedUsers.put(userId, userState);
+ getUserManagerInternal().setUserState(userId, userState.state);
updateStartedUserArrayLocked();
needStart = true;
}
@@ -813,15 +816,14 @@
// so we can just fairly silently bring the user back from
// the almost-dead.
uss.setState(uss.lastState);
- if (isUserRunningLocked(userId, FLAG_AND_UNLOCKING_OR_UNLOCKED)) {
- getUserManagerInternal().setUserUnlockingOrUnlocked(userId, true);
- }
+ getUserManagerInternal().setUserState(userId, uss.state);
updateStartedUserArrayLocked();
needStart = true;
} else if (uss.state == UserState.STATE_SHUTDOWN) {
// This means ACTION_SHUTDOWN has been sent, so we will
// need to treat this as a new boot of the user.
uss.setState(UserState.STATE_BOOTING);
+ getUserManagerInternal().setUserState(userId, uss.state);
updateStartedUserArrayLocked();
needStart = true;
}
@@ -938,6 +940,17 @@
boolean unlockUserCleared(final int userId, byte[] token, byte[] secret,
IProgressListener listener) {
synchronized (mService) {
+ // TODO Move this block outside of synchronized if it causes lock contention
+ if (!StorageManager.isUserKeyUnlocked(userId)) {
+ final UserInfo userInfo = getUserInfo(userId);
+ final IMountService mountService = getMountService();
+ try {
+ // We always want to unlock user storage, even user is not started yet
+ mountService.unlockUserKey(userId, userInfo.serialNumber, token, secret);
+ } catch (RemoteException | RuntimeException e) {
+ Slog.w(TAG, "Failed to unlock: " + e.getMessage());
+ }
+ }
// Bail if user isn't actually running, otherwise register the given
// listener to watch for unlock progress
final UserState uss = mStartedUsers.get(userId);
@@ -948,19 +961,6 @@
uss.mUnlockProgress.addListener(listener);
}
- // TODO Move this block outside of synchronized if it causes lock contention
- if (!StorageManager.isUserKeyUnlocked(userId)) {
- final UserInfo userInfo = getUserInfo(userId);
- final IMountService mountService = getMountService();
- try {
- mountService.unlockUserKey(userId, userInfo.serialNumber, token, secret);
- } catch (RemoteException | RuntimeException e) {
- Slog.w(TAG, "Failed to unlock: " + e.getMessage());
- notifyFinished(userId, listener);
- return false;
- }
- }
-
finishUserUnlocking(uss);
// We just unlocked a user, so let's now attempt to unlock any
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 32b9429..1698ab5 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -555,8 +555,7 @@
try {
// Restricted users are not allowed to create VPNs, they are tied to Owner
UserInfo user = mgr.getUserInfo(mUserHandle);
- if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN,
- new UserHandle(mUserHandle))) {
+ if (user.isRestricted()) {
throw new SecurityException("Restricted users cannot establish VPNs");
}
@@ -1055,18 +1054,27 @@
}
/**
- * @return {@code true} if the set of users blocked whilst waiting for VPN to connect includes
- * the UID {@param uid}, {@code false} otherwise.
+ * @return {@code true} if {@param uid} is blocked by an always-on VPN.
+ * A UID is blocked if it's included in one of the mBlockedUsers ranges and the VPN is
+ * not connected, or if the VPN is connected but does not apply to the UID.
*
* @see #mBlockedUsers
*/
public synchronized boolean isBlockingUid(int uid) {
- for (UidRange uidRange : mBlockedUsers) {
- if (uidRange.contains(uid)) {
- return true;
- }
+ if (!mLockdown) {
+ return false;
}
- return false;
+
+ if (mNetworkInfo.isConnected()) {
+ return !appliesToUid(uid);
+ } else {
+ for (UidRange uidRange : mBlockedUsers) {
+ if (uidRange.contains(uid)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
private native int jniCreate(int mtu);
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 2103cce..1b2ccd7 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -20,9 +20,11 @@
import android.accounts.Account;
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentService;
@@ -296,11 +298,12 @@
final int callingUserHandle = UserHandle.getCallingUserId();
// Registering an observer for any user other than the calling user requires uri grant or
// cross user permission
- if (callingUserHandle != userHandle &&
- mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
- != PackageManager.PERMISSION_GRANTED) {
- enforceCrossUserPermission(userHandle,
- "no permission to observe other users' provider view");
+ if (callingUserHandle != userHandle) {
+ if (checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION, userHandle)
+ != PackageManager.PERMISSION_GRANTED) {
+ enforceCrossUserPermission(userHandle,
+ "no permission to observe other users' provider view");
+ }
}
if (userHandle < 0) {
@@ -360,10 +363,11 @@
final int pid = Binder.getCallingPid();
final int callingUserHandle = UserHandle.getCallingUserId();
// Notify for any user other than the caller requires uri grant or cross user permission
- if (callingUserHandle != userHandle &&
- mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
- != PackageManager.PERMISSION_GRANTED) {
- enforceCrossUserPermission(userHandle, "no permission to notify other users");
+ if (callingUserHandle != userHandle) {
+ if (checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
+ userHandle) != PackageManager.PERMISSION_GRANTED) {
+ enforceCrossUserPermission(userHandle, "no permission to notify other users");
+ }
}
// We passed the permission check; resolve pseudouser targets as appropriate
@@ -389,9 +393,18 @@
for (int i=0; i<numCalls; i++) {
ObserverCall oc = calls.get(i);
try {
- oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);
+ // If the uri does not belong to the same user as the observer: we must add
+ // the userId to the uri. Otherewise the observer would think the uri belongs
+ // to his user.
+ final Uri tempUri;
+ if (oc.mObserverUserId != userHandle) {
+ tempUri = ContentProvider.maybeAddUserId(uri, userHandle);
+ } else {
+ tempUri = uri;
+ }
+ oc.mObserver.onChange(oc.mSelfChange, tempUri, userHandle);
if (DEBUG) Slog.d(TAG, "Notified " + oc.mObserver + " of " + "update at "
- + uri);
+ + tempUri);
} catch (RemoteException ex) {
synchronized (mRootNode) {
Log.w(TAG, "Found dead observer, removing");
@@ -427,6 +440,15 @@
}
}
+ private int checkUriPermission(Uri uri, int pid, int uid, int modeFlags, int userHandle) {
+ try {
+ return ActivityManagerNative.getDefault().checkUriPermission(
+ uri, pid, uid, modeFlags, userHandle, null);
+ } catch (RemoteException e) {
+ return PackageManager.PERMISSION_DENIED;
+ }
+ }
+
public void notifyChange(Uri uri, IContentObserver observer,
boolean observerWantsSelfNotifications, boolean syncToNetwork) {
notifyChange(uri, observer, observerWantsSelfNotifications,
@@ -444,11 +466,13 @@
final ObserverNode mNode;
final IContentObserver mObserver;
final boolean mSelfChange;
+ final int mObserverUserId;
- ObserverCall(ObserverNode node, IContentObserver observer, boolean selfChange) {
+ ObserverCall(ObserverNode node, IContentObserver observer, boolean selfChange, int observerUserId) {
mNode = node;
mObserver = observer;
mSelfChange = selfChange;
+ mObserverUserId = observerUserId;
}
}
@@ -1361,7 +1385,8 @@
if (DEBUG) Slog.d(TAG, "Reporting to " + entry.observer + ": leaf=" + leaf
+ " flags=" + Integer.toHexString(flags)
+ " desc=" + entry.notifyForDescendants);
- calls.add(new ObserverCall(this, entry.observer, selfChange));
+ calls.add(new ObserverCall(this, entry.observer, selfChange,
+ UserHandle.getUserId(entry.uid)));
}
}
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 0daa8ba..aa1d73f 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -222,7 +222,6 @@
private static native void nativeSetPointerIconType(long ptr, int iconId);
private static native void nativeReloadPointerIcons(long ptr);
private static native void nativeSetCustomPointerIcon(long ptr, PointerIcon icon);
- private static native void nativeSetPointerIconDetached(long ptr, boolean detached);
// Input event injection constants defined in InputDispatcher.h.
private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
@@ -1503,11 +1502,6 @@
nativeSetFocusedApplication(mPtr, application);
}
- @Override
- public void setPointerIconDetached(boolean detached) {
- nativeSetPointerIconDetached(mPtr, detached);
- }
-
public void setInputDispatchMode(boolean enabled, boolean frozen) {
nativeSetInputDispatchMode(mPtr, enabled, frozen);
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java
index 230c2e9..ea36170 100644
--- a/services/core/java/com/android/server/net/NetworkStatsObservers.java
+++ b/services/core/java/com/android/server/net/NetworkStatsObservers.java
@@ -190,11 +190,9 @@
private void handleUpdateStats(StatsContext statsContext) {
if (mDataUsageRequests.size() == 0) {
- if (LOGV) Slog.v(TAG, "No registered listeners of data usage");
return;
}
- if (LOGV) Slog.v(TAG, "Checking if any registered observer needs to be notified");
for (int i = 0; i < mDataUsageRequests.size(); i++) {
RequestInfo requestInfo = mDataUsageRequests.valueAt(i);
requestInfo.updateStats(statsContext);
@@ -371,9 +369,6 @@
NetworkStats stats = mCollection.getSummary(template,
Long.MIN_VALUE /* start */, Long.MAX_VALUE /* end */,
mAccessLevel, mCallingUid);
- if (LOGV) {
- Slog.v(TAG, "Netstats for " + template + ": " + stats);
- }
return stats.getTotalBytes();
}
}
@@ -391,11 +386,6 @@
for (int i = 0; i < uidsToMonitor.length; i++) {
long bytesSoFar = getTotalBytesForNetworkUid(mRequest.template, uidsToMonitor[i]);
-
- if (LOGV) {
- Slog.v(TAG, bytesSoFar + " bytes so far since notification for "
- + mRequest.template + " for uid=" + uidsToMonitor[i]);
- }
if (bytesSoFar > mRequest.thresholdInBytes) {
return true;
}
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 53c5a6d..dc85dd7 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -16,6 +16,10 @@
package com.android.server.notification;
+import static android.content.Context.BIND_ALLOW_WHITELIST_MANAGEMENT;
+import static android.content.Context.BIND_AUTO_CREATE;
+import static android.content.Context.BIND_FOREGROUND_SERVICE;
+
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.PendingIntent;
@@ -43,7 +47,6 @@
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
-import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
@@ -56,7 +59,6 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
-import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
@@ -681,7 +683,7 @@
};
if (!mContext.bindServiceAsUser(intent,
serviceConnection,
- Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+ BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT,
new UserHandle(userid))) {
mServicesBinding.remove(servicesBindingTag);
Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 946e4f7..b5a8bf3 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -40,11 +40,13 @@
import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_DEFAULT;
import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_NONE;
+
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import android.Manifest;
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
import android.app.ActivityManagerNative;
import android.app.AppGlobals;
import android.app.AppOpsManager;
@@ -56,6 +58,7 @@
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.app.PendingIntent;
+import android.app.RemoteInput;
import android.app.StatusBarManager;
import android.app.backup.BackupManager;
import android.app.usage.UsageEvents;
@@ -64,6 +67,7 @@
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
@@ -90,6 +94,7 @@
import android.os.IInterface;
import android.os.Looper;
import android.os.Message;
+import android.os.Parcelable;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -127,6 +132,7 @@
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
+import com.android.server.DeviceIdleController;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -2542,6 +2548,8 @@
+ " id=" + id + " notification=" + notification);
}
+ markAsSentFromNotification(notification);
+
// Sanitize inputs
notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN,
Notification.PRIORITY_MAX);
@@ -2556,6 +2564,63 @@
idOut[0] = id;
}
+ private static void markAsSentFromNotification(Notification notification) {
+ final ActivityManagerInternal am = LocalServices.getService(ActivityManagerInternal.class);
+ final long duration = LocalServices.getService(DeviceIdleController.LocalService.class)
+ .getNotificationWhitelistDuration();
+
+ int size = 0;
+ if (notification.contentIntent != null) {
+ am.setPendingIntentWhitelistDuration(notification.contentIntent.getTarget(), duration);
+ }
+ if (notification.deleteIntent != null) {
+ am.setPendingIntentWhitelistDuration(notification.deleteIntent.getTarget(), duration);
+ }
+ if (notification.fullScreenIntent != null) {
+ am.setPendingIntentWhitelistDuration(notification.fullScreenIntent.getTarget(),
+ duration);
+ }
+ if (notification.actions != null) {
+ for (Notification.Action action: notification.actions) {
+ am.setPendingIntentWhitelistDuration(action.actionIntent.getTarget(), duration);
+ setPendingIntentWhitelistDuration(am, duration, action.getExtras());
+ final RemoteInput[] remoteInputs = action.getRemoteInputs();
+ if (remoteInputs != null) {
+ for (RemoteInput remoteInput : remoteInputs) {
+ setPendingIntentWhitelistDuration(am, duration, remoteInput.getExtras());
+ }
+ }
+ }
+ }
+ }
+
+ private static void setPendingIntentWhitelistDuration(ActivityManagerInternal am, long duration,
+ Bundle extras) {
+ for (String key : extras.keySet()) {
+ setPendingIntentWhitelistDuration(am, duration, extras.getParcelable(key));
+ final Parcelable[] parcelableArray = extras.getParcelableArray(key);
+ if (parcelableArray != null) {
+ for (Parcelable parcelable: parcelableArray) {
+ setPendingIntentWhitelistDuration(am, duration, parcelable);
+ }
+ }
+ final ArrayList<Parcelable> parcelableList = extras.getParcelableArrayList(key);
+ if (parcelableList != null) {
+ for (Parcelable parcelable: parcelableList) {
+ setPendingIntentWhitelistDuration(am, duration, parcelable);
+ }
+ }
+ }
+ }
+
+ private static void setPendingIntentWhitelistDuration(ActivityManagerInternal am, long duration,
+ Parcelable parcelable) {
+ if (parcelable instanceof PendingIntent) {
+ am.setPendingIntentWhitelistDuration(((PendingIntent) parcelable).getTarget(),
+ duration);
+ }
+ }
+
private class EnqueueNotificationRunnable implements Runnable {
private final NotificationRecord r;
private final int userId;
@@ -3813,8 +3878,10 @@
@Override
public void onUserSwitched(int user) {
- for (ManagedServiceInfo info : mServices) {
- unregisterService(info.service, info.userid);
+ synchronized (mNotificationList) {
+ for (ManagedServiceInfo info : mServices) {
+ unregisterService(info.service, info.userid);
+ }
}
registerRanker();
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 7c89e9f..367f8cb 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -318,8 +318,12 @@
public void setContactAffinity(float contactAffinity) {
mContactAffinity = contactAffinity;
+ if (mImportance < IMPORTANCE_HIGH &&
+ mContactAffinity >= ValidateNotificationPeople.STARRED_CONTACT) {
+ setImportance(IMPORTANCE_HIGH, getPeopleExplanation());
+ }
if (mImportance < IMPORTANCE_DEFAULT &&
- mContactAffinity > ValidateNotificationPeople.VALID_CONTACT) {
+ mContactAffinity >= ValidateNotificationPeople.VALID_CONTACT) {
setImportance(IMPORTANCE_DEFAULT, getPeopleExplanation());
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index 00d7a7b..7b573da 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -384,7 +384,7 @@
noisyImportance = new ImportanceHistogram(context, "note_imp_noisy_");
quietImportance = new ImportanceHistogram(context, "note_imp_quiet_");
finalImportance = new ImportanceHistogram(context, "note_importance_");
- enqueueRate = new RateEstimator(mCreated);
+ enqueueRate = new RateEstimator();
}
public AggregatedStats getPrevious() {
diff --git a/services/core/java/com/android/server/notification/RateEstimator.java b/services/core/java/com/android/server/notification/RateEstimator.java
index 4dc30a4..c17db4a 100644
--- a/services/core/java/com/android/server/notification/RateEstimator.java
+++ b/services/core/java/com/android/server/notification/RateEstimator.java
@@ -25,30 +25,43 @@
public class RateEstimator {
private static final double RATE_ALPHA = 0.8;
private static final double MINIMUM_DT = 0.0005;
- private long mLastEventTime;
- private float mInterarrivalTime;
+ private Long mLastEventTime;
+ private Float mInterarrivalTime;
- public RateEstimator(long now) {
- mLastEventTime = now;
- }
+ public RateEstimator() {}
- /** Update the estimate to account for an event that jsut happened. */
+ /** Update the estimate to account for an event that just happened. */
public float update(long now) {
- mInterarrivalTime = (float) getInterarrivalEstimate(now);
+ float rate;
+ if (mLastEventTime == null) {
+ // No last event time, rate is zero.
+ rate = 0f;
+ } else {
+ // Calculate the new inter-arrival time based on last event time.
+ mInterarrivalTime = (float) getInterarrivalEstimate(now);
+ rate = (float) (1.0 / mInterarrivalTime);
+ }
mLastEventTime = now;
- return (float) (1.0 / mInterarrivalTime);
+ return rate;
}
/** @return the estimated rate if there were a new event right now. */
public float getRate(long now) {
+ if (mLastEventTime == null) {
+ return 0f;
+ }
return (float) (1.0 / getInterarrivalEstimate(now));
}
/** @return the average inter-arrival time if there were a new event right now. */
private double getInterarrivalEstimate(long now) {
- // a*iat_old + (1-a)*(t_now-t_last)
double dt = ((double) (now - mLastEventTime)) / 1000.0;
dt = Math.max(dt, MINIMUM_DT);
+ if (mInterarrivalTime == null) {
+ // No last inter-arrival time, return the new value directly.
+ return dt;
+ }
+ // a*iat_old + (1-a)*(t_now-t_last)
return (RATE_ALPHA * mInterarrivalTime + (1.0 - RATE_ALPHA) * dt);
}
}
diff --git a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
index 15a63ec..e3dcf14 100644
--- a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
+++ b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
@@ -36,6 +36,7 @@
import com.android.server.notification.NotificationManagerService.DumpFilter;
import java.io.PrintWriter;
+import java.util.Calendar;
import java.util.TimeZone;
/**
@@ -237,6 +238,14 @@
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) Slog.d(TAG, "onReceive " + intent.getAction());
+ if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
+ for (Uri conditionId : mSubscriptions.keySet()) {
+ final ScheduleCalendar cal = mSubscriptions.get(conditionId);
+ if (cal != null) {
+ cal.setTimeZone(Calendar.getInstance().getTimeZone());
+ }
+ }
+ }
evaluateSubscriptions();
}
};
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 35bcaa9..08b9c78 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -16300,11 +16300,11 @@
final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);
removeKeystoreDataIfNeeded(userId, appId);
- final UserManager um = mContext.getSystemService(UserManager.class);
+ UserManagerInternal umInternal = getUserManagerInternal();
final int flags;
- if (um.isUserUnlockingOrUnlocked(userId)) {
+ if (umInternal.isUserUnlockingOrUnlocked(userId)) {
flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
- } else if (um.isUserRunning(userId)) {
+ } else if (umInternal.isUserRunning(userId)) {
flags = StorageManager.FLAG_STORAGE_DE;
} else {
flags = 0;
@@ -19063,11 +19063,12 @@
// Reconcile app data for all started/unlocked users
final StorageManager sm = mContext.getSystemService(StorageManager.class);
final UserManager um = mContext.getSystemService(UserManager.class);
+ UserManagerInternal umInternal = getUserManagerInternal();
for (UserInfo user : um.getUsers()) {
final int flags;
- if (um.isUserUnlockingOrUnlocked(user.id)) {
+ if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
- } else if (um.isUserRunning(user.id)) {
+ } else if (umInternal.isUserRunning(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE;
} else {
continue;
@@ -19491,11 +19492,12 @@
}
final UserManager um = mContext.getSystemService(UserManager.class);
+ UserManagerInternal umInternal = getUserManagerInternal();
for (UserInfo user : um.getUsers()) {
final int flags;
- if (um.isUserUnlockingOrUnlocked(user.id)) {
+ if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
- } else if (um.isUserRunning(user.id)) {
+ } else if (umInternal.isUserRunning(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE;
} else {
continue;
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 33ccf16..9d8ba12 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -22,7 +22,6 @@
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SystemApi;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
@@ -31,9 +30,7 @@
import android.app.IActivityManager;
import android.app.IStopUserCallback;
import android.app.KeyguardManager;
-import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -76,6 +73,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.util.Xml;
@@ -88,6 +86,7 @@
import com.android.internal.util.XmlUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
+import com.android.server.am.UserState;
import libcore.io.IoUtils;
import libcore.util.Objects;
@@ -329,8 +328,8 @@
@GuardedBy("mUsersLock")
private boolean mForceEphemeralUsers;
- @GuardedBy("mUsersLock")
- private final SparseBooleanArray mUnlockingOrUnlockedUsers = new SparseBooleanArray();
+ @GuardedBy("mUserStates")
+ private final SparseIntArray mUserStates = new SparseIntArray();
private static UserManagerService sInstance;
@@ -377,6 +376,7 @@
mLocalService = new LocalService();
LocalServices.addService(UserManagerInternal.class, mLocalService);
mLockPatternUtils = new LockPatternUtils(mContext);
+ mUserStates.put(UserHandle.USER_SYSTEM, UserState.STATE_BOOTING);
}
void systemReady() {
@@ -2375,7 +2375,9 @@
synchronized (mUsersLock) {
mUsers.remove(userHandle);
mIsUserManaged.delete(userHandle);
- mUnlockingOrUnlockedUsers.delete(userHandle);
+ }
+ synchronized (mUserStates) {
+ mUserStates.delete(userHandle);
}
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.remove(userHandle);
@@ -3055,6 +3057,9 @@
pw.println();
pw.println(" Device managed: " + mIsDeviceManaged);
}
+ synchronized (mUserStates) {
+ pw.println(" Started users state: " + mUserStates);
+ }
// Dump some capabilities
pw.println();
pw.println(" Max users: " + UserManager.getMaxSupportedUsers());
@@ -3241,16 +3246,32 @@
}
@Override
- public void setUserUnlockingOrUnlocked(int userId, boolean unlockingOrUnlocked) {
- synchronized (mUsersLock) {
- mUnlockingOrUnlockedUsers.put(userId, unlockingOrUnlocked);
+ public boolean isUserRunning(int userId) {
+ synchronized (mUserStates) {
+ return mUserStates.get(userId, -1) >= 0;
+ }
+ }
+
+ @Override
+ public void setUserState(int userId, int userState) {
+ synchronized (mUserStates) {
+ mUserStates.put(userId, userState);
+ }
+ }
+
+ @Override
+ public void removeUserState(int userId) {
+ synchronized (mUserStates) {
+ mUserStates.delete(userId);
}
}
@Override
public boolean isUserUnlockingOrUnlocked(int userId) {
- synchronized (mUsersLock) {
- return mUnlockingOrUnlockedUsers.get(userId);
+ synchronized (mUserStates) {
+ int state = mUserStates.get(userId, -1);
+ return (state == UserState.STATE_RUNNING_UNLOCKING)
+ || (state == UserState.STATE_RUNNING_UNLOCKED);
}
}
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 2f72607..0cafb93 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2589,8 +2589,15 @@
final PhoneWindow win = new PhoneWindow(context);
win.setIsStartingWindow(true);
+ final WindowManager.LayoutParams params = win.getAttributes();
final Resources r = context.getResources();
- win.setTitle(r.getText(labelRes, nonLocalizedLabel));
+ CharSequence label = r.getText(labelRes);
+ // Only change the accessibility title if the label is localized
+ if (label != null) {
+ win.setTitle(label, true);
+ } else {
+ win.setTitle(nonLocalizedLabel, false);
+ }
win.setType(
WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
@@ -2624,7 +2631,6 @@
win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT);
- final WindowManager.LayoutParams params = win.getAttributes();
params.token = appToken;
params.packageName = packageName;
params.windowAnimations = win.getWindowStyle().getResourceId(
@@ -5421,7 +5427,7 @@
// If the service process is killed, then ask it to clean up after itself
final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
SYSUI_SCREENSHOT_ERROR_RECEIVER);
- Intent errorIntent = new Intent();
+ Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
errorIntent.setComponent(errorComponent);
errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
Intent.FLAG_RECEIVER_FOREGROUND);
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 101f56f..8be5dfb 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -1203,9 +1203,6 @@
window.layer = windowState.mLayer;
window.token = windowState.mClient.asBinder();
window.title = windowState.mAttrs.accessibilityTitle;
- if (window.title == null) {
- window.title = windowState.mAttrs.getTitle();
- }
window.accessibilityIdOfAnchor = windowState.mAttrs.accessibilityIdOfAnchor;
WindowState attachedWindow = windowState.mAttachedWindow;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index b773a4e..f57e83aa 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -451,6 +451,16 @@
destroySurfaces();
}
+ void markSavedSurfaceExiting() {
+ for (int i = allAppWindows.size() - 1; i >= 0; i--) {
+ final WindowState w = allAppWindows.get(i);
+ if (w.isAnimatingInvisibleWithSavedSurface()) {
+ w.mAnimatingExit = true;
+ w.mWinAnimator.mAnimating = true;
+ }
+ }
+ }
+
void restoreSavedSurfaces() {
if (!canRestoreSurfaces()) {
clearVisibleBeforeClientHidden();
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 1b31d07c..e73649d 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -45,9 +45,11 @@
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
+import android.view.inputmethod.InputMethodManagerInternal;
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DockedDividerUtils;
+import com.android.server.LocalServices;
import com.android.server.wm.DimLayer.DimLayerUser;
import com.android.server.wm.WindowManagerService.H;
@@ -131,6 +133,7 @@
private float mLastAnimationProgress;
private float mLastDividerProgress;
private final DividerSnapAlgorithm[] mSnapAlgorithmForRotation = new DividerSnapAlgorithm[4];
+ private boolean mImeHideRequested;
DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
mService = service;
@@ -375,11 +378,39 @@
}
}
mDockedStackListeners.finishBroadcast();
- if (!exists) {
+ if (exists) {
+ InputMethodManagerInternal inputMethodManagerInternal =
+ LocalServices.getService(InputMethodManagerInternal.class);
+ if (inputMethodManagerInternal != null) {
+
+ // Hide the current IME to avoid problems with animations from IME adjustment when
+ // attaching the docked stack.
+ inputMethodManagerInternal.hideCurrentInputMethod();
+ mImeHideRequested = true;
+ }
+ } else {
setMinimizedDockedStack(false);
}
}
+ /**
+ * Resets the state that IME hide has been requested. See {@link #isImeHideRequested}.
+ */
+ void resetImeHideRequested() {
+ mImeHideRequested = false;
+ }
+
+ /**
+ * The docked stack divider controller makes sure the IME gets hidden when attaching the docked
+ * stack, to avoid animation problems. This flag indicates whether the request to hide the IME
+ * has been sent in an asynchronous manner, and the IME should be treated as hidden already.
+ *
+ * @return whether IME hide request has been sent
+ */
+ boolean isImeHideRequested() {
+ return mImeHideRequested;
+ }
+
void notifyDockedStackMinimizedChanged(boolean minimizedDock, long animDuration) {
mService.mH.removeMessages(NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED);
mService.mH.obtainMessage(NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED,
@@ -606,7 +637,12 @@
private void setMinimizedDockedStack(boolean minimized) {
final TaskStack stack = mDisplayContent.getDockedStackVisibleForUserLocked();
notifyDockedStackMinimizedChanged(minimized, 0);
- setMinimizeAmount(stack, minimized ? 1f : 0f);
+ if (stack == null) {
+ return;
+ }
+ if (stack.setAdjustedForMinimizedDock(minimized ? 1f : 0f)) {
+ mService.mWindowPlacerLocked.performSurfacePlacement();
+ }
}
private boolean isAnimationMaximizing() {
@@ -690,8 +726,11 @@
float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration);
t = (isAnimationMaximizing() ? TOUCH_RESPONSE_INTERPOLATOR : mMinimizedDockInterpolator)
.getInterpolation(t);
- setMinimizeAmount(stack, getMinimizeAmount(stack, t));
-
+ if (stack != null) {
+ if (stack.setAdjustedForMinimizedDock(getMinimizeAmount(stack, t))) {
+ mService.mWindowPlacerLocked.performSurfacePlacement();
+ }
+ }
if (t >= 1.0f) {
mAnimatingForMinimizedDockedStack = false;
return false;
@@ -700,42 +739,6 @@
}
}
- void setMinimizeAmount(TaskStack dockedStack, float minimizeAmount) {
- final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
-
- // If the docked stack is not visible, clear the complementary stack on all stacks.
- if (dockedStack == null) {
- for (int i = stacks.size() - 1; i >= 0; --i) {
- final TaskStack stack = stacks.get(i);
- stack.resetAdjustedForComplementDock();
- }
- return;
- }
-
- // Otherwise if the docked stack minimize amount has changed, update the adjusted bounds
- // on the other stack that's currently visible, so that the stack's getDimBounds()
- // occupies what's left by the docked stack. This is needed so that stuff like wallpaper
- // gets cropped properly to the area left by the dock.
- if (dockedStack.setAdjustedForMinimizedDock(minimizeAmount)) {
- final boolean adjusted =
- dockedStack.isVisibleForUserLocked() && minimizeAmount != 0.0f;
- dockedStack.getDimBounds(mTmpRect2);
- int dockSide = dockedStack.getDockSide();
- for (int i = stacks.size() - 1; i >= 0; --i) {
- final TaskStack stack = stacks.get(i);
- if (stack == dockedStack) {
- continue;
- }
- if (stack.isVisibleLocked() && adjusted) {
- stack.setAdjustedForComplementDock(mTmpRect2, dockSide);
- } else {
- stack.resetAdjustedForComplementDock();
- }
- }
- mService.mWindowPlacerLocked.performSurfacePlacement();
- }
- }
-
private float getInterpolatedAnimationValue(float t) {
return t * mAnimationTarget + (1 - t) * mAnimationStart;
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index f51fd8a..8be5b19 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
@@ -122,7 +123,6 @@
private float mAdjustImeAmount;
private float mAdjustDividerAmount;
private final int mDockedStackMinimizeThickness;
- private boolean mAdjustedForForComplementDock;
// If this is true, we are in the bounds animating mode.
// The task will be down or upscaled to perfectly fit the
@@ -242,9 +242,7 @@
insetBounds = mFullyAdjustedImeBounds;
}
}
- if (!mAdjustedForForComplementDock) {
- alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : mBounds, insetBounds);
- }
+ alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : mBounds, insetBounds);
mDisplayContent.layoutNeeded = true;
}
@@ -380,6 +378,11 @@
}
private boolean updateBoundsAfterConfigChange() {
+ if (mDisplayContent == null) {
+ // If the stack is already detached we're not updating anything,
+ // as it's going away soon anyway.
+ return false;
+ }
final int newRotation = getDisplayInfo().rotation;
final int newDensity = getDisplayInfo().logicalDensityDpi;
@@ -403,6 +406,13 @@
snapDockedStackAfterRotation(mTmpRect2);
final int newDockSide = getDockSide(mTmpRect2);
if (oldDockSide != newDockSide) {
+ // Update the dock create mode and clear the dock create bounds, these
+ // might change after a rotation and the original values will be invalid.
+ mService.setDockedStackCreateStateLocked(
+ (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
+ ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
+ : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT,
+ null);
mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
}
}
@@ -851,7 +861,6 @@
mImeWin = imeWin;
mImeGoingAway = false;
if (!mAdjustedForIme || forceUpdate) {
- mAdjustedForForComplementDock = false;
mAdjustedForIme = true;
mAdjustImeAmount = 0f;
mAdjustDividerAmount = 0f;
@@ -914,12 +923,10 @@
* @return Whether the amount has changed and a layout is needed.
*/
boolean setAdjustedForMinimizedDock(float minimizeAmount) {
- mAdjustedForForComplementDock = false;
-
if (minimizeAmount != mMinimizeAmount) {
mMinimizeAmount = minimizeAmount;
updateAdjustedBounds();
- return true;
+ return isVisibleForUserLocked();
} else {
return false;
}
@@ -929,33 +936,6 @@
return mMinimizeAmount != 0f;
}
- void setAdjustedForComplementDock(Rect dockBounds, int dockSide) {
- if (mMinimizeAmount != 0f || mAdjustedForIme) {
- return;
- }
- mTmpAdjustedBounds.set(mBounds);
- if (dockSide == DOCKED_TOP) {
- mTmpAdjustedBounds.top = dockBounds.bottom;
- } else if (dockSide == DOCKED_LEFT) {
- mTmpAdjustedBounds.left = dockBounds.right;
- } else if (dockSide == DOCKED_RIGHT) {
- mTmpAdjustedBounds.right = dockBounds.left;
- } else {
- Slog.w(TAG_WM, "setAdjustedForComplementDock: invalid dock side " + dockSide);
- return;
- }
- mAdjustedForForComplementDock = true;
- setAdjustedBounds(mTmpAdjustedBounds);
- }
-
- void resetAdjustedForComplementDock() {
- if (mAdjustedForForComplementDock) {
- mAdjustedForForComplementDock = false;
- mTmpAdjustedBounds.setEmpty();
- setAdjustedBounds(mTmpAdjustedBounds);
- }
- }
-
/**
* Puts all visible tasks that are adjusted for IME into resizing mode and adds the windows
* to the list of to be drawn windows the service is waiting for.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index aaed8ca..3f4c1d5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2277,6 +2277,19 @@
}
}
+ private void setupWindowForRemoveOnExit(WindowState win) {
+ win.mRemoveOnExit = true;
+ win.setDisplayLayoutNeeded();
+ // Request a focus update as this window's input channel is already gone. Otherwise
+ // we could have no focused window in input manager.
+ final boolean focusChanged = updateFocusedWindowLocked(
+ UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
+ mWindowPlacerLocked.performSurfacePlacement();
+ if (focusChanged) {
+ mInputMonitor.updateInputWindowsLw(false /*force*/);
+ }
+ }
+
public void removeWindow(Session session, IWindow client) {
synchronized(mWindowMap) {
WindowState win = windowForClientLocked(session, client, false);
@@ -2358,14 +2371,7 @@
// Do not set mAnimatingExit to true here, it will cause the surface to be hidden
// immediately after the enter animation is done. If the app is not yet drawn then
// it will show up as a flicker.
- win.mRemoveOnExit = true;
- // Request a focus update as this window's input channel is already gone. Otherwise
- // we could have no focused window in input manager.
- final boolean focusChanged = updateFocusedWindowLocked(
- UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
- if (focusChanged) {
- mInputMonitor.updateInputWindowsLw(false /*force*/);
- }
+ setupWindowForRemoveOnExit(win);
Binder.restoreCallingIdentity(origId);
return;
}
@@ -2417,17 +2423,10 @@
// The exit animation is running or should run... wait for it!
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
"Not removing " + win + " due to exit animation ");
- win.mRemoveOnExit = true;
- win.setDisplayLayoutNeeded();
- final boolean focusChanged = updateFocusedWindowLocked(
- UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
- mWindowPlacerLocked.performSurfacePlacement();
+ setupWindowForRemoveOnExit(win);
if (appToken != null) {
appToken.updateReportedVisibilityLocked();
}
- if (focusChanged) {
- mInputMonitor.updateInputWindowsLw(false /*force*/);
- }
Binder.restoreCallingIdentity(origId);
return;
}
@@ -2835,6 +2834,8 @@
}
win.mRelayoutCalled = true;
+ win.mInRelayout = true;
+
final int oldVisibility = win.mViewVisibility;
win.mViewVisibility = viewVisibility;
if (DEBUG_SCREEN_ON) {
@@ -2975,6 +2976,7 @@
if (DEBUG_LAYOUT) {
Slog.v(TAG_WM, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
}
+ win.mInRelayout = false;
}
if (configChanged) {
@@ -3567,6 +3569,8 @@
final ArrayList<Task> tasks = displayContent.getTasks();
final boolean inMultiWindow = isStackVisibleLocked(DOCKED_STACK_ID)
|| isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID);
+ final boolean dockMinimized =
+ getDefaultDisplayContentLocked().mDividerControllerLocked.isMinimizedDock();
for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
final int firstToken = tokens.size() - 1;
@@ -3601,8 +3605,10 @@
continue;
}
- // No app except the home app may specify the screen orientation in multi-window.
- if (inMultiWindow && !atoken.mTask.isHomeTask()) {
+ // No app except the home app may specify the screen orientation in multi-window,
+ // and only if the docked stack is minimized to avoid weirdness when home task
+ // temporarily gets moved to the front.
+ if (inMultiWindow && (!atoken.mTask.isHomeTask() || !dockMinimized)) {
continue;
}
@@ -4960,11 +4966,15 @@
public void setDockedStackCreateState(int mode, Rect bounds) {
synchronized (mWindowMap) {
- mDockedStackCreateMode = mode;
- mDockedStackCreateBounds = bounds;
+ setDockedStackCreateStateLocked(mode, bounds);
}
}
+ void setDockedStackCreateStateLocked(int mode, Rect bounds) {
+ mDockedStackCreateMode = mode;
+ mDockedStackCreateBounds = bounds;
+ }
+
/**
* Create a new TaskStack and place it on a DisplayContent.
* @param stackId The unique identifier of the new stack.
@@ -6387,6 +6397,11 @@
if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM,
"Taking screenshot while rotating");
+ // We force pending transactions to flush before taking
+ // the screenshot by pushing an empty synchronous transaction.
+ SurfaceControl.openTransaction();
+ SurfaceControl.closeTransactionSync();
+
bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
inRotation, rot);
if (bm == null) {
@@ -7585,7 +7600,8 @@
void adjustForImeIfNeeded(final DisplayContent displayContent) {
final WindowState imeWin = mInputMethodWindow;
- final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw();
+ final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
+ && !displayContent.mDividerControllerLocked.isImeHideRequested();
final boolean dockVisible = isStackVisibleLocked(DOCKED_STACK_ID);
final TaskStack imeTargetStack = getImeFocusStackLocked();
final int imeDockSide = (dockVisible && imeTargetStack != null) ?
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c15afb3..ff95afc 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -362,6 +362,8 @@
*/
boolean mRelayoutCalled;
+ boolean mInRelayout;
+
/**
* If the application has called relayout() with changes that can
* impact its window's size, we need to perform a layout pass on it
@@ -1630,6 +1632,12 @@
return task != null && task.inDockedWorkspace();
}
+ // TODO: Strange usage of word workspace here and above.
+ boolean inPinnedWorkspace() {
+ final Task task = getTask();
+ return task != null && task.inPinnedWorkspace();
+ }
+
boolean isDockedInEffect() {
final Task task = getTask();
return task != null && task.isDockedInEffect();
@@ -2111,7 +2119,9 @@
void clearHasSavedSurface() {
mSurfaceSaved = false;
mAnimatingWithSavedSurface = false;
- mWasVisibleBeforeClientHidden = false;
+ if (mWasVisibleBeforeClientHidden) {
+ mAppToken.destroySavedSurfaces();
+ }
}
boolean clearAnimatingWithSavedSurface() {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 42eddd5..37d6faf5 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -23,7 +23,6 @@
import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.server.wm.AppWindowAnimator.sDummyAnimation;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
@@ -1328,33 +1327,6 @@
return;
}
- // We crop wallpaper windows to the stack bounds of their current target to avoid them
- // showing behind transparent windows in other stacks in split-screen mode.
- if (w.getBaseType() == TYPE_WALLPAPER) {
- final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
- if (wallpaperTarget != null) {
- final Task task = wallpaperTarget.getTask();
- final WindowStateAnimator winAnimator = wallpaperTarget.mWinAnimator;
- // We can only crop the wallpaper using final crop with stack bounds if the target
- // is not animating, or if it's animating with clip mode STACK_CLIP_AFTER_ANIM.
- // If it's animating with mode STACK_CLIP_NONE, we shouldn't crop either the task
- // itself or the wallpaper. If it's animating with STACK_CLIP_BEFORE_ANIM, the crop
- // is before the transform on the task itself.
- final boolean useFinalCropOnWallpaper = !winAnimator.isAnimationSet()
- || winAnimator.resolveStackClip() == STACK_CLIP_AFTER_ANIM;
- if (task != null && !task.isFullscreen()
- && task.cropWindowsToStackBounds()
- && useFinalCropOnWallpaper){
- final TaskStack stack = task.mStack;
- if (stack != null && !stack.isFullscreen()) {
- stack.getDimBounds(mTmpStackBounds);
- finalClipRect.set(mTmpStackBounds);
- }
- }
- }
- return;
- }
-
final Task task = w.getTask();
if (task == null || !task.cropWindowsToStackBounds()) {
return;
@@ -1428,8 +1400,24 @@
float extraHScale = (float) 1.0;
float extraVScale = (float) 1.0;
- mSurfaceResized = mSurfaceController.setSizeInTransaction(
- mTmpSize.width(), mTmpSize.height(), recoveringMemory);
+ // Once relayout has been called at least once, we need to make sure
+ // we only resize the client surface during calls to relayout. For
+ // clients which use indeterminate measure specs (MATCH_PARENT),
+ // we may try and change their window size without a call to relayout.
+ // However, this would be unsafe, as the client may be in the middle
+ // of producing a frame at the old size, having just completed layout
+ // to find the surface size changed underneath it.
+ //
+ // TODO: For N we only apply this fix to the pinned workspace. As we
+ // aren't observing known issues here outside of PiP resizing. (Typically
+ // the other windows that use -1 are PopupWindows which aren't likely
+ // to be rendering while we resize).
+ if (!w.inPinnedWorkspace() || (!w.mRelayoutCalled || w.mInRelayout)) {
+ mSurfaceResized = mSurfaceController.setSizeInTransaction(
+ mTmpSize.width(), mTmpSize.height(), recoveringMemory);
+ } else {
+ mSurfaceResized = false;
+ }
mForceScaleUntilResize = mForceScaleUntilResize && !mSurfaceResized;
@@ -1437,10 +1425,12 @@
if ((task != null && task.mStack.getForceScaleToCrop()) || mForceScaleUntilResize) {
int hInsets = w.getAttrs().surfaceInsets.left + w.getAttrs().surfaceInsets.right;
int vInsets = w.getAttrs().surfaceInsets.top + w.getAttrs().surfaceInsets.bottom;
+ float surfaceWidth = mSurfaceController.getWidth();
+ float surfaceHeight = mSurfaceController.getHeight();
// We want to calculate the scaling based on the content area, not based on
// the entire surface, so that we scale in sync with windows that don't have insets.
- extraHScale = (mTmpClipRect.width() - hInsets) / (float)(mTmpSize.width() - hInsets);
- extraVScale = (mTmpClipRect.height() - vInsets) / (float)(mTmpSize.height() - vInsets);
+ extraHScale = (mTmpClipRect.width() - hInsets) / (float)(surfaceWidth - hInsets);
+ extraVScale = (mTmpClipRect.height() - vInsets) / (float)(surfaceHeight - vInsets);
// In the case of ForceScaleToCrop we scale entire tasks together,
// and so we need to scale our offsets relative to the task bounds
@@ -1462,14 +1452,14 @@
// Since we are scaled to fit in our previously desired crop, we can now
// expose the whole window in buffer space, and not risk extending
// past where the system would have cropped us
- mTmpClipRect.set(0, 0, mTmpSize.width(), mTmpSize.height());
+ mTmpClipRect.set(0, 0, (int)surfaceWidth, (int)surfaceHeight);
mTmpFinalClipRect.setEmpty();
// Various surfaces in the scaled stack may resize at different times.
// We need to ensure for each surface, that we disable transformation matrix
// scaling in the same transaction which we resize the surface in.
// As we are in SCALING_MODE_SCALE_TO_WINDOW, SurfaceFlinger will
- // then take over the scaling until the new buffer arrives, and things
+ // then take over the scaling until the new buffer arrives, and things
// will be seamless.
mForceScaleUntilResize = true;
} else {
@@ -1755,6 +1745,10 @@
mWin.mAppToken.onFirstWindowDrawn(mWin, this);
}
+ if (mWin.mAttrs.type == TYPE_INPUT_METHOD) {
+ mWin.mDisplayContent.mDividerControllerLocked.resetImeHideRequested();
+ }
+
return true;
}
return false;
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index af47369..9646a49 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -454,6 +454,15 @@
return mSurfaceY;
}
+ float getWidth() {
+ return mSurfaceW;
+ }
+
+ float getHeight() {
+ return mSurfaceH;
+ }
+
+
public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
if (dumpAll) {
pw.print(prefix); pw.print("mSurface="); pw.println(mSurfaceControl);
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 308b24d..4148cd0 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1301,6 +1301,14 @@
appsCount = mService.mClosingApps.size();
for (int i = 0; i < appsCount; i++) {
AppWindowToken wtoken = mService.mClosingApps.valueAt(i);
+
+ // If we still have some windows animating with saved surfaces that's
+ // either invisible or already removed, mark them exiting so that they
+ // are disposed of after the exit animation. These are not supposed to
+ // be shown, or are delayed removal until app is actually drawn (in which
+ // case the window will be removed after the animation).
+ wtoken.markSavedSurfaceExiting();
+
final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
appAnimator.clearThumbnail();
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 2e82cec..2f72a5c 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -207,7 +207,6 @@
void setPointerIconType(int32_t iconId);
void reloadPointerIcons();
void setCustomPointerIcon(const SpriteIcon& icon);
- void setPointerIconDetached(bool detached);
/* --- InputReaderPolicyInterface implementation --- */
@@ -712,14 +711,6 @@
mInputManager->getDispatcher()->setFocusedApplication(applicationHandle);
}
-void NativeInputManager::setPointerIconDetached(bool detached) {
- AutoMutex _l(mLock);
- sp<PointerController> controller = mLocked.pointerController.promote();
- if (controller != NULL) {
- controller->detachPointerIcon(detached);
- }
-}
-
void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
mInputManager->getDispatcher()->setInputDispatchMode(enabled, frozen);
}
@@ -1332,12 +1323,6 @@
im->setFocusedApplication(env, applicationHandleObj);
}
-static void nativeSetPointerIconDetached(JNIEnv* env, jclass /* clazz */, jlong ptr,
- jboolean detached) {
- NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
- im->setPointerIconDetached(detached);
-}
-
static void nativeSetInputDispatchMode(JNIEnv* /* env */,
jclass /* clazz */, jlong ptr, jboolean enabled, jboolean frozen) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
@@ -1520,8 +1505,6 @@
(void*) nativeSetInputWindows },
{ "nativeSetFocusedApplication", "(JLcom/android/server/input/InputApplicationHandle;)V",
(void*) nativeSetFocusedApplication },
- { "nativeSetPointerIconDetached", "(JZ)V",
- (void*) nativeSetPointerIconDetached },
{ "nativeSetInputDispatchMode", "(JZZ)V",
(void*) nativeSetInputDispatchMode },
{ "nativeSetSystemUiVisibility", "(JI)V",
diff --git a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
index 8ea9bfc..06d2031 100644
--- a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
+++ b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
@@ -78,7 +78,7 @@
env->ThrowNew(exceptionClass, methodName);
}
-static bool IsValidCallbackThread() {
+static bool IsValidCallbackThreadEnvOnly() {
JNIEnv* env = AndroidRuntime::getJNIEnv();
if(sCallbackEnv == NULL || sCallbackEnv != env) {
@@ -89,6 +89,20 @@
return true;
}
+static bool IsValidCallbackThread() {
+ // sCallbacksObject is created when FlpHardwareProvider on Java side is
+ // initialized. Sometimes the hardware may call a function before the Java
+ // side is ready. In order to prevent a system crash, check whether
+ // sCallbacksObj has been created. If not, simply ignore this event from
+ // hardware.
+ if (sCallbacksObj == NULL) {
+ ALOGE("Attempt to use FlpHardwareProvider blocked, because it hasn't been initialized.");
+ return false;
+ }
+
+ return IsValidCallbackThreadEnvOnly();
+}
+
static void BatchingCapabilitiesCallback(int32_t capabilities) {
if(!IsValidCallbackThread()) {
return;
@@ -154,7 +168,7 @@
}
case DISASSOCIATE_JVM:
{
- if (!IsValidCallbackThread()) {
+ if (!IsValidCallbackThreadEnvOnly()) {
ALOGE(
"Attempted to dissasociate an unnownk callback thread : '%s'.",
__FUNCTION__
@@ -661,16 +675,6 @@
TranslateToObject(lastLocation, locationObject);
}
- // sCallbacksObject is created when FlpHardwareProvider on Java side is
- // initialized. Sometimes the hardware may call this function before the Java
- // side is ready. In order to prevent the system crash, check whether
- // sCallbacksObj has been created. If not, simply ignore this event from
- // hardware.
- if (sCallbacksObj == NULL) {
- ALOGE("FlpHardwareProvider hasn't been initialized.");
- return;
- }
-
sCallbackEnv->CallVoidMethod(
sCallbacksObj,
sOnGeofenceMonitorStatus,
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index e29452a..e8d4c58 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -72,15 +72,18 @@
#define GPS_MAX_SATELLITE_COUNT 32
#define GNSS_MAX_SATELLITE_COUNT 64
-// Let these through, with ID remapped by offset
+// Let these through, with ID remapped down to 1, 2... by offset
#define GLONASS_SVID_OFFSET 64
#define GLONASS_SVID_COUNT 24
#define BEIDOU_SVID_OFFSET 200
#define BEIDOU_SVID_COUNT 35
+// Let these through, with ID remapped up (33->120 ... 64->151, etc.)
+#define SBAS_SVID_MIN 33
+#define SBAS_SVID_MAX 64
+#define SBAS_SVID_ADD 87
+
// Let these through, with no ID remapping
-#define SBAS_SVID_MIN 120
-#define SBAS_SVID_MAX 151
#define QZSS_SVID_MIN 193
#define QZSS_SVID_MAX 200
@@ -159,6 +162,7 @@
info.svid -= BEIDOU_SVID_OFFSET;
} else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
info.constellation = GNSS_CONSTELLATION_SBAS;
+ info.svid += SBAS_SVID_ADD;
} else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
info.constellation = GNSS_CONSTELLATION_QZSS;
} else {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index c1913de..1af9ccb 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3810,14 +3810,13 @@
// If caller has PO (or DO) it can change the password, so see if that's the case first.
ActiveAdmin admin = getActiveAdminWithPolicyForUidLocked(
null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, callingUid);
+ final boolean preN = getTargetSdk(admin.info.getPackageName(),
+ userHandle) <= android.os.Build.VERSION_CODES.M;
if (admin == null) {
// Otherwise, make sure the caller has any active admin with the right policy.
admin = getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
- final boolean preN = getTargetSdk(admin.info.getPackageName(), userHandle)
- <= android.os.Build.VERSION_CODES.M;
-
// As of N, password resetting to empty/null is not allowed anymore.
// TODO Should we allow DO/PO to set an empty password?
if (TextUtils.isEmpty(password)) {
@@ -3838,6 +3837,30 @@
}
}
}
+ // Do not allow to reset password when current user has a managed profile
+ if (!isManagedProfile(userHandle)) {
+ for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
+ if (userInfo.isManagedProfile()) {
+ if (!preN) {
+ throw new IllegalStateException(
+ "Cannot reset password on user has managed profile");
+ } else {
+ Slog.e(LOG_TAG, "Cannot reset password on user has managed profile");
+ return false;
+ }
+ }
+ }
+ }
+ // Do not allow to reset password when user is locked
+ if (!mUserManager.isUserUnlocked(userHandle)) {
+ if (!preN) {
+ throw new IllegalStateException("Cannot reset password when user is locked");
+ } else {
+ Slog.e(LOG_TAG, "Cannot reset password when user is locked");
+ return false;
+ }
+ }
+
quality = getPasswordQuality(null, userHandle, /* parent */ false);
if (quality == DevicePolicyManager.PASSWORD_QUALITY_MANAGED) {
quality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e306d89..eed4351 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -176,7 +176,7 @@
* visual content.
*/
private static final int DEFAULT_SYSTEM_THEME =
- com.android.internal.R.style.Theme_Material_Light_DarkActionBar;
+ com.android.internal.R.style.Theme_DeviceDefault_Light_DarkActionBar;
private final int mFactoryTestMode;
private Timer mProfilerSnapshotTimer;
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 538e8f8..485f2f5 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -597,12 +597,13 @@
private void generateIPv4FilterLocked(ApfGenerator gen) throws IllegalInstructionException {
// Here's a basic summary of what the IPv4 filter program does:
//
- // if it's multicast and we're dropping multicast:
- // drop
- // if it's not broadcast:
- // pass
- // if it's not DHCP destined to our MAC:
- // drop
+ // if filtering multicast (i.e. multicast lock not held):
+ // if it's multicast:
+ // drop
+ // if it's not broadcast:
+ // pass
+ // if it's not DHCP destined to our MAC:
+ // drop
// pass
if (mMulticastFilter) {
@@ -610,27 +611,27 @@
gen.addLoad8(Register.R0, IPV4_DEST_ADDR_OFFSET);
gen.addAnd(0xf0);
gen.addJumpIfR0Equals(0xe0, gen.DROP_LABEL);
- }
- // Drop all broadcasts besides DHCP addressed to us
- // If not a broadcast packet, pass
- gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
- gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, gen.PASS_LABEL);
- // If not UDP, drop
- gen.addLoad8(Register.R0, IPV4_PROTOCOL_OFFSET);
- gen.addJumpIfR0NotEquals(IPPROTO_UDP, gen.DROP_LABEL);
- // If fragment, drop. This matches the BPF filter installed by the DHCP client.
- gen.addLoad16(Register.R0, IPV4_FRAGMENT_OFFSET_OFFSET);
- gen.addJumpIfR0AnyBitsSet(IPV4_FRAGMENT_OFFSET_MASK, gen.DROP_LABEL);
- // If not to DHCP client port, drop
- gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
- gen.addLoad16Indexed(Register.R0, UDP_DESTINATION_PORT_OFFSET);
- gen.addJumpIfR0NotEquals(DHCP_CLIENT_PORT, gen.DROP_LABEL);
- // If not DHCP to our MAC address, drop
- gen.addLoadImmediate(Register.R0, DHCP_CLIENT_MAC_OFFSET);
- // NOTE: Relies on R1 containing IPv4 header offset.
- gen.addAddR1();
- gen.addJumpIfBytesNotEqual(Register.R0, mHardwareAddress, gen.DROP_LABEL);
+ // Drop all broadcasts besides DHCP addressed to us
+ // If not a broadcast packet, pass
+ gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
+ gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, gen.PASS_LABEL);
+ // If not UDP, drop
+ gen.addLoad8(Register.R0, IPV4_PROTOCOL_OFFSET);
+ gen.addJumpIfR0NotEquals(IPPROTO_UDP, gen.DROP_LABEL);
+ // If fragment, drop. This matches the BPF filter installed by the DHCP client.
+ gen.addLoad16(Register.R0, IPV4_FRAGMENT_OFFSET_OFFSET);
+ gen.addJumpIfR0AnyBitsSet(IPV4_FRAGMENT_OFFSET_MASK, gen.DROP_LABEL);
+ // If not to DHCP client port, drop
+ gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
+ gen.addLoad16Indexed(Register.R0, UDP_DESTINATION_PORT_OFFSET);
+ gen.addJumpIfR0NotEquals(DHCP_CLIENT_PORT, gen.DROP_LABEL);
+ // If not DHCP to our MAC address, drop
+ gen.addLoadImmediate(Register.R0, DHCP_CLIENT_MAC_OFFSET);
+ // NOTE: Relies on R1 containing IPv4 header offset.
+ gen.addAddR1();
+ gen.addJumpIfBytesNotEqual(Register.R0, mHardwareAddress, gen.DROP_LABEL);
+ }
// Otherwise, pass
gen.addJump(gen.PASS_LABEL);
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index 99b10c3..96c852b 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -84,7 +84,7 @@
public class DhcpClient extends StateMachine {
private static final String TAG = "DhcpClient";
- private static final boolean DBG = false;
+ private static final boolean DBG = true;
private static final boolean STATE_DBG = false;
private static final boolean MSG_DBG = false;
private static final boolean PACKET_DBG = false;
diff --git a/services/tests/servicestests/src/android/net/apf/ApfTest.java b/services/tests/servicestests/src/android/net/apf/ApfTest.java
index 9e04d23..fae82ca 100644
--- a/services/tests/servicestests/src/android/net/apf/ApfTest.java
+++ b/services/tests/servicestests/src/android/net/apf/ApfTest.java
@@ -663,7 +663,7 @@
@LargeTest
public void testApfFilterIPv4() throws Exception {
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
- ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, false /* multicastFilter */);
+ ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, true /* multicastFilter */);
byte[] program = ipManagerCallback.getApfProgram();
// Verify empty packet of 100 zero bytes is passed
@@ -726,46 +726,57 @@
byte[] program = ipManagerCallback.getApfProgram();
// Construct IPv4 and IPv6 multicast packets.
- ByteBuffer v4packet = ByteBuffer.wrap(new byte[100]);
- v4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
- v4packet.position(IPV4_DEST_ADDR_OFFSET);
- v4packet.put(new byte[]{(byte)224,0,0,1});
+ ByteBuffer mcastv4packet = ByteBuffer.wrap(new byte[100]);
+ mcastv4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
+ mcastv4packet.position(IPV4_DEST_ADDR_OFFSET);
+ mcastv4packet.put(new byte[]{(byte)224,0,0,1});
- ByteBuffer v6packet = ByteBuffer.wrap(new byte[100]);
- v6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
- v6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP);
- v6packet.position(IPV6_DEST_ADDR_OFFSET);
- v6packet.put(new byte[]{(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb});
+ ByteBuffer mcastv6packet = ByteBuffer.wrap(new byte[100]);
+ mcastv6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
+ mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP);
+ mcastv6packet.position(IPV6_DEST_ADDR_OFFSET);
+ mcastv6packet.put(new byte[]{(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb});
+
+ // Construct IPv4 broadcast packet.
+ ByteBuffer bcastv4packet = ByteBuffer.wrap(new byte[100]);
+ bcastv4packet.put(ETH_BROADCAST_MAC_ADDRESS);
+ bcastv4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
+ bcastv4packet.position(IPV4_DEST_ADDR_OFFSET);
+ bcastv4packet.put(new byte[]{(byte)192,(byte)0,(byte)2,(byte)63});
// Verify initially disabled multicast filter is off
- assertPass(program, v4packet.array(), 0);
- assertPass(program, v6packet.array(), 0);
+ assertPass(program, bcastv4packet.array(), 0);
+ assertPass(program, mcastv4packet.array(), 0);
+ assertPass(program, mcastv6packet.array(), 0);
// Turn on multicast filter and verify it works
ipManagerCallback.resetApfProgramWait();
apfFilter.setMulticastFilter(true);
program = ipManagerCallback.getApfProgram();
- assertDrop(program, v4packet.array(), 0);
- assertDrop(program, v6packet.array(), 0);
+ assertDrop(program, bcastv4packet.array(), 0);
+ assertDrop(program, mcastv4packet.array(), 0);
+ assertDrop(program, mcastv6packet.array(), 0);
// Turn off multicast filter and verify it's off
ipManagerCallback.resetApfProgramWait();
apfFilter.setMulticastFilter(false);
program = ipManagerCallback.getApfProgram();
- assertPass(program, v4packet.array(), 0);
- assertPass(program, v6packet.array(), 0);
+ assertPass(program, bcastv4packet.array(), 0);
+ assertPass(program, mcastv4packet.array(), 0);
+ assertPass(program, mcastv6packet.array(), 0);
// Verify it can be initialized to on
ipManagerCallback.resetApfProgramWait();
apfFilter.shutdown();
apfFilter = new TestApfFilter(ipManagerCallback, true /* multicastFilter */);
program = ipManagerCallback.getApfProgram();
- assertDrop(program, v4packet.array(), 0);
- assertDrop(program, v6packet.array(), 0);
+ assertDrop(program, bcastv4packet.array(), 0);
+ assertDrop(program, mcastv4packet.array(), 0);
+ assertDrop(program, mcastv6packet.array(), 0);
// Verify that ICMPv6 multicast is not dropped.
- v6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
- assertPass(program, v6packet.array(), 0);
+ mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
+ assertPass(program, mcastv6packet.array(), 0);
apfFilter.shutdown();
}
diff --git a/services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java b/services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java
index cc0920f..b5698d5 100644
--- a/services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java
@@ -26,18 +26,18 @@
@Override
public void setUp() {
mTestStartTime = 1225731600000L;
- mEstimator = new RateEstimator(mTestStartTime);
+ mEstimator = new RateEstimator();
}
@SmallTest
public void testRunningTimeBackwardDoesntExplodeUpdate() throws Exception {
- final float rate = mEstimator.update(mTestStartTime - 1000L);
- assertFalse(Float.isInfinite(rate));
- assertFalse(Float.isNaN(rate));
+ assertUpdateTime(mTestStartTime);
+ assertUpdateTime(mTestStartTime - 1000L);
}
@SmallTest
public void testRunningTimeBackwardDoesntExplodeGet() throws Exception {
+ assertUpdateTime(mTestStartTime);
final float rate = mEstimator.getRate(mTestStartTime - 1000L);
assertFalse(Float.isInfinite(rate));
assertFalse(Float.isNaN(rate));
@@ -45,13 +45,14 @@
@SmallTest
public void testInstantaneousEventsDontExplodeUpdate() throws Exception {
- final float rate = mEstimator.update(mTestStartTime);
- assertFalse(Float.isInfinite(rate));
- assertFalse(Float.isNaN(rate));
+ assertUpdateTime(mTestStartTime);
+ assertUpdateTime(mTestStartTime);
}
@SmallTest
public void testInstantaneousEventsDontExplodeGet() throws Exception {
+ assertUpdateTime(mTestStartTime);
+ assertUpdateTime(mTestStartTime);
final float rate = mEstimator.getRate(mTestStartTime);
assertFalse(Float.isInfinite(rate));
assertFalse(Float.isNaN(rate));
@@ -59,6 +60,7 @@
@SmallTest
public void testCompactBurstIsEstimatedUnderTwoPercent() throws Exception {
+ assertUpdateTime(mTestStartTime);
long eventStart = mTestStartTime + 1000; // start event a long time after initialization
long nextEventTime = postEvents(eventStart, 1, 5); // five events at 1000Hz
final float rate = mEstimator.getRate(nextEventTime);
@@ -67,6 +69,7 @@
@SmallTest
public void testSustained1000HzBurstIsEstimatedOverNinetyPercent() throws Exception {
+ assertUpdateTime(mTestStartTime);
long eventStart = mTestStartTime + 1000; // start event a long time after initialization
long nextEventTime = postEvents(eventStart, 1, 100); // one hundred events at 1000Hz
final float rate = mEstimator.getRate(nextEventTime);
@@ -75,6 +78,7 @@
@SmallTest
public void testSustained100HzBurstIsEstimatedOverNinetyPercent() throws Exception {
+ assertUpdateTime(mTestStartTime);
long eventStart = mTestStartTime + 1000; // start event a long time after initialization
long nextEventTime = postEvents(eventStart, 10, 100); // one hundred events at 100Hz
final float rate = mEstimator.getRate(nextEventTime);
@@ -84,6 +88,7 @@
@SmallTest
public void testRecoverQuicklyAfterSustainedBurst() throws Exception {
+ assertUpdateTime(mTestStartTime);
long eventStart = mTestStartTime + 1000; // start event a long time after initialization
long nextEventTime = postEvents(eventStart, 10, 1000); // one hundred events at 100Hz
final float rate = mEstimator.getRate(nextEventTime + 5000L); // two seconds later
@@ -92,12 +97,19 @@
@SmallTest
public void testEstimateShouldNotOvershoot() throws Exception {
+ assertUpdateTime(mTestStartTime);
long eventStart = mTestStartTime + 1000; // start event a long time after initialization
long nextEventTime = postEvents(eventStart, 1, 1000); // one thousand events at 1000Hz
final float rate = mEstimator.getRate(nextEventTime);
assertLessThan("Rate", rate, 1000f);
}
+ @SmallTest
+ public void testGetRateWithoutUpdate() throws Exception {
+ final float rate = mEstimator.getRate(mTestStartTime);
+ assertLessThan("Rate", rate, 0.1f);
+ }
+
private void assertLessThan(String label, float a, float b) {
assertTrue(String.format("%s was %f, but should be less than %f", label, a, b), a < b);
}
@@ -115,4 +127,10 @@
}
return time;
}
+
+ private void assertUpdateTime(long time) {
+ final float rate = mEstimator.update(time);
+ assertFalse(Float.isInfinite(rate));
+ assertFalse(Float.isNaN(rate));
+ }
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 78efd05..613fae4 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -837,28 +837,9 @@
* @param subId the subscription ID, normally obtained from {@link SubscriptionManager}.
* @return A {@link PersistableBundle} containing the config for the given subId, or default
* values for an invalid subId.
- *
- * @deprecated use getConfig.
*/
@Nullable
public PersistableBundle getConfigForSubId(int subId) {
- return getConfig(subId);
- }
-
- /**
- * Gets the configuration values for a particular subscription, which is associated with a
- * specific SIM card. If an invalid subId is used, the returned config will contain default
- * values.
- *
- * <p>Requires Permission:
- * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
- *
- * @param subId the subscription ID, normally obtained from {@link SubscriptionManager}.
- * @return A {@link PersistableBundle} containing the config for the given subId, or default
- * values for an invalid subId.
- */
- @Nullable
- public PersistableBundle getConfig(int subId) {
try {
ICarrierConfigLoader loader = getICarrierConfigLoader();
if (loader == null) {
@@ -880,11 +861,11 @@
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*
- * @return A {@link PersistableBundle} containing the config for the default subscription.
+ * @see #getConfigForSubId
*/
@Nullable
public PersistableBundle getConfig() {
- return getConfig(SubscriptionManager.getDefaultSubscriptionId());
+ return getConfigForSubId(SubscriptionManager.getDefaultSubscriptionId());
}
/**
@@ -901,29 +882,8 @@
* {@link android.service.carrier.CarrierService#onLoadConfig} will be called from an
* arbitrary thread.
* </p>
- *
- * @deprecated use notifyConfigChanged.
*/
public void notifyConfigChangedForSubId(int subId) {
- notifyConfigChanged(subId);
- }
-
- /**
- * Calling this method triggers telephony services to fetch the current carrier configuration.
- * <p>
- * Normally this does not need to be called because the platform reloads config on its own.
- * This should be called by a carrier service app if it wants to update config at an arbitrary
- * moment.
- * </p>
- * <p>Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
- * <p>
- * This method returns before the reload has completed, and
- * {@link android.service.carrier.CarrierService#onLoadConfig} will be called from an
- * arbitrary thread.
- * </p>
- */
- public void notifyConfigChanged(int subId) {
try {
ICarrierConfigLoader loader = getICarrierConfigLoader();
if (loader == null) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 5fed594..2304346 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -66,6 +66,12 @@
* a reference to an instance through
* {@link android.content.Context#getSystemService
* Context.getSystemService(Context.TELEPHONY_SERVICE)}.
+ *
+ * The returned TelephonyManager will use the default subscription for all calls.
+ * To call an API for a specific subscription, use {@link #createForSubscriptionId(int)}. e.g.
+ * <code>
+ * telephonyManager = defaultSubTelephonyManager.createForSubscriptionId(subId);
+ * </code>
* <p>
* Note that access to some telephony information is
* permission-protected. Your application cannot access the protected
@@ -101,6 +107,7 @@
}
private final Context mContext;
+ private final int mSubId;
private SubscriptionManager mSubscriptionManager;
private static String multiSimConfig =
@@ -121,6 +128,12 @@
/** @hide */
public TelephonyManager(Context context) {
+ this(context, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
+ }
+
+ /** @hide */
+ public TelephonyManager(Context context, int subId) {
+ mSubId = subId;
Context appContext = context.getApplicationContext();
if (appContext != null) {
mContext = appContext;
@@ -138,6 +151,7 @@
/** @hide */
private TelephonyManager() {
mContext = null;
+ mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
private static TelephonyManager sInstance = new TelephonyManager();
@@ -231,6 +245,16 @@
return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
}
+ /**
+ * Create a new TelephonyManager object pinned to the given subscription ID.
+ *
+ * @return a TelephonyManager that uses the given subId for all calls.
+ */
+ public TelephonyManager createForSubscriptionId(int subId) {
+ // Don't reuse any TelephonyManager objects.
+ return new TelephonyManager(mContext, subId);
+ }
+
/** {@hide} */
public boolean isMultiSimEnabled() {
return (multiSimConfig.equals("dsds") || multiSimConfig.equals("dsda") ||
@@ -923,7 +947,7 @@
* @hide
*/
public void enableLocationUpdates() {
- enableLocationUpdates(getDefaultSubscription());
+ enableLocationUpdates(getSubId());
}
/**
@@ -935,8 +959,8 @@
* CONTROL_LOCATION_UPDATES}
*
* @param subId for which the location updates are enabled
+ * @hide
*/
- /** @hide */
public void enableLocationUpdates(int subId) {
try {
ITelephony telephony = getITelephony();
@@ -957,7 +981,7 @@
* @hide
*/
public void disableLocationUpdates() {
- disableLocationUpdates(getDefaultSubscription());
+ disableLocationUpdates(getSubId());
}
/** @hide */
@@ -1018,7 +1042,7 @@
*/
@SystemApi
public int getCurrentPhoneType() {
- return getCurrentPhoneType(getDefaultSubscription());
+ return getCurrentPhoneType(getSubId());
}
/**
@@ -1029,8 +1053,8 @@
* @see #PHONE_TYPE_CDMA
*
* @param subId for which phone type is returned
+ * @hide
*/
- /** {@hide} */
@SystemApi
public int getCurrentPhoneType(int subId) {
int phoneId;
@@ -1258,7 +1282,7 @@
* on a CDMA network).
*/
public String getNetworkOperatorName() {
- return getNetworkOperatorName(getDefaultSubscription());
+ return getNetworkOperatorName(getSubId());
}
/**
@@ -1269,6 +1293,7 @@
* unreliable on CDMA networks (use {@link #getPhoneType()} to determine if
* on a CDMA network).
* @param subId
+ * @hide
*/
public String getNetworkOperatorName(int subId) {
int phoneId = SubscriptionManager.getPhoneId(subId);
@@ -1295,6 +1320,7 @@
* on a CDMA network).
*
* @param subId
+ * @hide
*/
public String getNetworkOperator(int subId) {
int phoneId = SubscriptionManager.getPhoneId(subId);
@@ -1323,7 +1349,7 @@
* Availability: Only when user registered to a network.
*/
public boolean isNetworkRoaming() {
- return isNetworkRoaming(getDefaultSubscription());
+ return isNetworkRoaming(getSubId());
}
/**
@@ -1333,6 +1359,7 @@
* Availability: Only when user registered to a network.
*
* @param subId
+ * @hide
*/
public boolean isNetworkRoaming(int subId) {
int phoneId = SubscriptionManager.getPhoneId(subId);
@@ -1361,6 +1388,7 @@
* on a CDMA network).
*
* @param subId for which Network CountryIso is returned
+ * @hide
*/
public String getNetworkCountryIso(int subId) {
int phoneId = SubscriptionManager.getPhoneId(subId);
@@ -1469,6 +1497,7 @@
* <p>
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * @hide
*/
public int getNetworkType(int subId) {
try {
@@ -1513,10 +1542,9 @@
* <p>
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
- * @hide
*/
public int getDataNetworkType() {
- return getDataNetworkType(getDefaultSubscription());
+ return getDataNetworkType(getSubId());
}
/**
@@ -1529,6 +1557,7 @@
* <p>
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * @hide
*/
public int getDataNetworkType(int subId) {
try{
@@ -1554,10 +1583,9 @@
* <p>
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
- * @hide
*/
public int getVoiceNetworkType() {
- return getVoiceNetworkType(getDefaultSubscription());
+ return getVoiceNetworkType(getSubId());
}
/**
@@ -1566,6 +1594,7 @@
* <p>
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * @hide
*/
public int getVoiceNetworkType(int subId) {
try{
@@ -1835,6 +1864,7 @@
* @see #getSimState
*
* @param subId for which SimOperator is returned
+ * @hide
*/
public String getSimOperator(int subId) {
return getSimOperatorNumeric(subId);
@@ -1911,6 +1941,7 @@
* @see #getSimState
*
* @param subId for which SimOperatorName is returned
+ * @hide
*/
public String getSimOperatorName(int subId) {
int phoneId = SubscriptionManager.getPhoneId(subId);
@@ -1938,6 +1969,7 @@
* Returns the ISO country code equivalent for the SIM provider's country code.
*
* @param subId for which SimCountryIso is returned
+ * @hide
*/
public String getSimCountryIso(int subId) {
int phoneId = SubscriptionManager.getPhoneId(subId);
@@ -1962,7 +1994,7 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
public String getSimSerialNumber() {
- return getSimSerialNumber(getDefaultSubscription());
+ return getSimSerialNumber(getSubId());
}
/**
@@ -1972,6 +2004,7 @@
* @param subId for which Sim Serial number is returned
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * @hide
*/
public String getSimSerialNumber(int subId) {
try {
@@ -2002,7 +2035,7 @@
* @hide
*/
public int getLteOnCdmaMode() {
- return getLteOnCdmaMode(getDefaultSubscription());
+ return getLteOnCdmaMode(getSubId());
}
/**
@@ -2017,8 +2050,8 @@
* <p>
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * @hide
*/
- /** {@hide} */
public int getLteOnCdmaMode(int subId) {
try {
ITelephony telephony = getITelephony();
@@ -2048,7 +2081,7 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
public String getSubscriberId() {
- return getSubscriberId(getDefaultSubscription());
+ return getSubscriberId(getSubId());
}
/**
@@ -2060,6 +2093,7 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*
* @param subId whose subscriber id is returned
+ * @hide
*/
public String getSubscriberId(int subId) {
try {
@@ -2104,6 +2138,7 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*
* @param subId whose subscriber id is returned
+ * @hide
*/
public String getGroupIdLevel1(int subId) {
try {
@@ -2131,7 +2166,7 @@
* The default SMS app can also use this.
*/
public String getLine1Number() {
- return getLine1Number(getDefaultSubscription());
+ return getLine1Number(getSubId());
}
/**
@@ -2146,6 +2181,7 @@
* The default SMS app can also use this.
*
* @param subId whose phone number for line 1 is returned
+ * @hide
*/
public String getLine1Number(int subId) {
String number = null;
@@ -2186,7 +2222,7 @@
* @return true if the operation was executed correctly.
*/
public boolean setLine1NumberForDisplay(String alphaTag, String number) {
- return setLine1NumberForDisplay(getDefaultSubscription(), alphaTag, number);
+ return setLine1NumberForDisplay(getSubId(), alphaTag, number);
}
/**
@@ -2202,6 +2238,7 @@
* @param alphaTag alpha-tagging of the dailing nubmer
* @param number The dialing number
* @return true if the operation was executed correctly.
+ * @hide
*/
public boolean setLine1NumberForDisplay(int subId, String alphaTag, String number) {
try {
@@ -2224,7 +2261,7 @@
* nobody seems to call this.
*/
public String getLine1AlphaTag() {
- return getLine1AlphaTag(getDefaultSubscription());
+ return getLine1AlphaTag(getSubId());
}
/**
@@ -2236,6 +2273,7 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* @param subId whose alphabetic identifier associated with line 1 is returned
* nobody seems to call this.
+ * @hide
*/
public String getLine1AlphaTag(int subId) {
String alphaTag = null;
@@ -2292,7 +2330,7 @@
* @hide
*/
public String getMsisdn() {
- return getMsisdn(getDefaultSubscription());
+ return getMsisdn(getSubId());
}
/**
@@ -2303,8 +2341,8 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*
* @param subId for which msisdn is returned
+ * @hide
*/
- /** {@hide} */
public String getMsisdn(int subId) {
try {
IPhoneSubInfo info = getSubscriberInfo();
@@ -2326,7 +2364,7 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
public String getVoiceMailNumber() {
- return getVoiceMailNumber(getDefaultSubscription());
+ return getVoiceMailNumber(getSubId());
}
/**
@@ -2336,6 +2374,7 @@
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* @param subId whose voice mail number is returned
+ * @hide
*/
public String getVoiceMailNumber(int subId) {
try {
@@ -2360,7 +2399,7 @@
* @hide
*/
public String getCompleteVoiceMailNumber() {
- return getCompleteVoiceMailNumber(getDefaultSubscription());
+ return getCompleteVoiceMailNumber(getSubId());
}
/**
@@ -2370,8 +2409,8 @@
* {@link android.Manifest.permission#CALL_PRIVILEGED CALL_PRIVILEGED}
*
* @param subId
+ * @hide
*/
- /** {@hide} */
public String getCompleteVoiceMailNumber(int subId) {
try {
IPhoneSubInfo info = getSubscriberInfo();
@@ -2396,7 +2435,7 @@
* @param number The voicemail number.
*/
public boolean setVoiceMailNumber(String alphaTag, String number) {
- return setVoiceMailNumber(getDefaultSubscription(), alphaTag, number);
+ return setVoiceMailNumber(getSubId(), alphaTag, number);
}
/**
@@ -2408,6 +2447,7 @@
* @param subId The subscription id.
* @param alphaTag The alpha tag to display.
* @param number The voicemail number.
+ * @hide
*/
public boolean setVoiceMailNumber(int subId, String alphaTag, String number) {
try {
@@ -2429,7 +2469,7 @@
* @hide
*/
public int getVoiceMessageCount() {
- return getVoiceMessageCount(getDefaultSubscription());
+ return getVoiceMessageCount(getSubId());
}
/**
@@ -2438,8 +2478,8 @@
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* @param subId whose voice message count is returned
+ * @hide
*/
- /** {@hide} */
public int getVoiceMessageCount(int subId) {
try {
ITelephony telephony = getITelephony();
@@ -2462,7 +2502,7 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
public String getVoiceMailAlphaTag() {
- return getVoiceMailAlphaTag(getDefaultSubscription());
+ return getVoiceMailAlphaTag(getSubId());
}
/**
@@ -2473,6 +2513,7 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* @param subId whose alphabetic identifier associated with the
* voice mail number is returned
+ * @hide
*/
public String getVoiceMailAlphaTag(int subId) {
try {
@@ -2590,6 +2631,7 @@
* for a subscription.
*
* @param subId whose call state is returned
+ * @hide
*/
public int getCallState(int subId) {
int phoneId = SubscriptionManager.getPhoneId(subId);
@@ -2759,7 +2801,7 @@
* @hide
*/
public int getCdmaEriIconIndex() {
- return getCdmaEriIconIndex(getDefaultSubscription());
+ return getCdmaEriIconIndex(getSubId());
}
/**
@@ -2767,8 +2809,8 @@
* <p>
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * @hide
*/
- /** {@hide} */
public int getCdmaEriIconIndex(int subId) {
try {
ITelephony telephony = getITelephony();
@@ -2794,7 +2836,7 @@
* @hide
*/
public int getCdmaEriIconMode() {
- return getCdmaEriIconMode(getDefaultSubscription());
+ return getCdmaEriIconMode(getSubId());
}
/**
@@ -2805,8 +2847,8 @@
* <p>
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * @hide
*/
- /** {@hide} */
public int getCdmaEriIconMode(int subId) {
try {
ITelephony telephony = getITelephony();
@@ -2830,7 +2872,7 @@
* @hide
*/
public String getCdmaEriText() {
- return getCdmaEriText(getDefaultSubscription());
+ return getCdmaEriText(getSubId());
}
/**
@@ -2839,8 +2881,8 @@
* <p>
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * @hide
*/
- /** {@hide} */
public String getCdmaEriText(int subId) {
try {
ITelephony telephony = getITelephony();
@@ -2993,7 +3035,7 @@
* @return an IccOpenLogicalChannelResponse object.
*/
public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID) {
- return iccOpenLogicalChannel(getDefaultSubscription(), AID);
+ return iccOpenLogicalChannel(getSubId(), AID);
}
/**
@@ -3008,6 +3050,7 @@
* @param subId The subscription to use.
* @param AID Application id. See ETSI 102.221 and 101.220.
* @return an IccOpenLogicalChannelResponse object.
+ * @hide
*/
public IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID) {
try {
@@ -3034,7 +3077,7 @@
* @return true if the channel was closed successfully.
*/
public boolean iccCloseLogicalChannel(int channel) {
- return iccCloseLogicalChannel(getDefaultSubscription(), channel);
+ return iccCloseLogicalChannel(getSubId(), channel);
}
/**
@@ -3050,6 +3093,7 @@
* @param channel is the channel id to be closed as retruned by a successful
* iccOpenLogicalChannel.
* @return true if the channel was closed successfully.
+ * @hide
*/
public boolean iccCloseLogicalChannel(int subId, int channel) {
try {
@@ -3085,7 +3129,7 @@
*/
public String iccTransmitApduLogicalChannel(int channel, int cla,
int instruction, int p1, int p2, int p3, String data) {
- return iccTransmitApduLogicalChannel(getDefaultSubscription(), channel, cla,
+ return iccTransmitApduLogicalChannel(getSubId(), channel, cla,
instruction, p1, p2, p3, data);
}
@@ -3110,6 +3154,7 @@
* @param data Data to be sent with the APDU.
* @return The APDU response from the ICC card with the status appended at
* the end.
+ * @hide
*/
public String iccTransmitApduLogicalChannel(int subId, int channel, int cla,
int instruction, int p1, int p2, int p3, String data) {
@@ -3145,7 +3190,7 @@
*/
public String iccTransmitApduBasicChannel(int cla,
int instruction, int p1, int p2, int p3, String data) {
- return iccTransmitApduBasicChannel(getDefaultSubscription(), cla,
+ return iccTransmitApduBasicChannel(getSubId(), cla,
instruction, p1, p2, p3, data);
}
@@ -3168,6 +3213,7 @@
* @param data Data to be sent with the APDU.
* @return The APDU response from the ICC card with the status appended at
* the end.
+ * @hide
*/
public String iccTransmitApduBasicChannel(int subId, int cla,
int instruction, int p1, int p2, int p3, String data) {
@@ -3199,7 +3245,7 @@
*/
public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
String filePath) {
- return iccExchangeSimIO(getDefaultSubscription(), fileID, command, p1, p2, p3, filePath);
+ return iccExchangeSimIO(getSubId(), fileID, command, p1, p2, p3, filePath);
}
/**
@@ -3217,6 +3263,7 @@
* @param p3 P3 value of the APDU command.
* @param filePath
* @return The APDU response.
+ * @hide
*/
public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2,
int p3, String filePath) {
@@ -3245,7 +3292,7 @@
* returns an empty string.
*/
public String sendEnvelopeWithStatus(String content) {
- return sendEnvelopeWithStatus(getDefaultSubscription(), content);
+ return sendEnvelopeWithStatus(getSubId(), content);
}
/**
@@ -3262,6 +3309,7 @@
* @return The APDU response from the ICC card in hexadecimal format
* with the last 4 bytes being the status word. If the command fails,
* returns an empty string.
+ * @hide
*/
public String sendEnvelopeWithStatus(int subId, String content) {
try {
@@ -3381,6 +3429,19 @@
}
/**
+ * Return an appropriate subscription ID for any situation.
+ *
+ * If this object has been created with {@link #createForSubscriptionId}, then the provided
+ * subId is returned. Otherwise, the default subId will be returned.
+ */
+ private int getSubId() {
+ if (mSubId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
+ return getDefaultSubscription();
+ }
+ return mSubId;
+ }
+
+ /**
* Returns Default subscription.
*/
private static int getDefaultSubscription() {
@@ -3662,7 +3723,7 @@
* @see #hasCarrierPrivileges
*/
public String getIccAuthentication(int appType, int authType, String data) {
- return getIccAuthentication(getDefaultSubscription(), appType, authType, data);
+ return getIccAuthentication(getSubId(), appType, authType, data);
}
/**
@@ -3680,8 +3741,8 @@
* @return the response of authentication, or null if not available
*
* @see #hasCarrierPrivileges
+ * @hide
*/
-
public String getIccAuthentication(int subId, int appType, int authType, String data) {
try {
IPhoneSubInfo info = getSubscriberInfo();
@@ -3760,6 +3821,7 @@
* Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @hide
+ * TODO: Add an overload that takes no args.
*/
public void setNetworkSelectionModeAutomatic(int subId) {
try {
@@ -3785,6 +3847,7 @@
* Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @hide
+ * TODO: Add an overload that takes no args.
*/
public CellNetworkScanResult getCellNetworkScanResults(int subId) {
try {
@@ -3808,6 +3871,7 @@
* Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @hide
+ * TODO: Add an overload that takes no args.
*/
public boolean setNetworkSelectionModeManual(int subId, OperatorInfo operator,
boolean persistSelection) {
@@ -3859,7 +3923,7 @@
* @return true on success; false on any failure.
*/
public boolean setPreferredNetworkTypeToGlobal() {
- return setPreferredNetworkTypeToGlobal(getDefaultSubscription());
+ return setPreferredNetworkTypeToGlobal(getSubId());
}
/**
@@ -3870,6 +3934,7 @@
* @see #hasCarrierPrivileges
*
* @return true on success; false on any failure.
+ * @hide
*/
public boolean setPreferredNetworkTypeToGlobal(int subId) {
return setPreferredNetworkType(subId, RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
@@ -3919,7 +3984,7 @@
* @return true if the app has carrier privileges.
*/
public boolean hasCarrierPrivileges() {
- return hasCarrierPrivileges(getDefaultSubscription());
+ return hasCarrierPrivileges(getSubId());
}
/**
@@ -3931,12 +3996,13 @@
*
* @param subId The subscription to use.
* @return true if the app has carrier privileges.
+ * @hide
*/
public boolean hasCarrierPrivileges(int subId) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getCarrierPrivilegeStatus(subId) ==
+ return telephony.getCarrierPrivilegeStatus(mSubId) ==
CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
}
} catch (RemoteException ex) {
@@ -3962,7 +4028,7 @@
* @return true if the operation was executed correctly.
*/
public boolean setOperatorBrandOverride(String brand) {
- return setOperatorBrandOverride(getDefaultSubscription(), brand);
+ return setOperatorBrandOverride(getSubId(), brand);
}
/**
@@ -3979,6 +4045,7 @@
* @param subId The subscription to use.
* @param brand The brand name to display/set.
* @return true if the operation was executed correctly.
+ * @hide
*/
public boolean setOperatorBrandOverride(int subId, String brand) {
try {
@@ -4015,7 +4082,7 @@
public boolean setRoamingOverride(List<String> gsmRoamingList,
List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
List<String> cdmaNonRoamingList) {
- return setRoamingOverride(getDefaultSubscription(), gsmRoamingList, gsmNonRoamingList,
+ return setRoamingOverride(getSubId(), gsmRoamingList, gsmNonRoamingList,
cdmaRoamingList, cdmaNonRoamingList);
}
@@ -4062,7 +4129,7 @@
/** @hide */
@SystemApi
public String getCdmaMdn() {
- return getCdmaMdn(getDefaultSubscription());
+ return getCdmaMdn(getSubId());
}
/** @hide */
@@ -4083,7 +4150,7 @@
/** @hide */
@SystemApi
public String getCdmaMin() {
- return getCdmaMin(getDefaultSubscription());
+ return getCdmaMin(getSubId());
}
/** @hide */
@@ -4626,7 +4693,8 @@
* retrieves value for setting "name", and if that is not found throws
* SettingNotFoundException
*
- * @hide */
+ * @hide
+ */
public static int getIntWithSubId(ContentResolver cr, String name, int subId)
throws SettingNotFoundException {
try {
diff --git a/test-runner/src/android/test/mock/MockContentProvider.java b/test-runner/src/android/test/mock/MockContentProvider.java
index 3743fb0..5ef71df 100644
--- a/test-runner/src/android/test/mock/MockContentProvider.java
+++ b/test-runner/src/android/test/mock/MockContentProvider.java
@@ -41,12 +41,7 @@
* Mock implementation of ContentProvider. All methods are non-functional and throw
* {@link java.lang.UnsupportedOperationException}. Tests can extend this class to
* implement behavior needed for tests.
- *
- * @deprecated Use a mocking framework like <a href="https://github.com/mockito/mockito">Mockito</a>.
- * New tests should be written using the
- * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
*/
-@Deprecated
public class MockContentProvider extends ContentProvider {
/*
* Note: if you add methods to ContentProvider, you must add similar methods to
diff --git a/test-runner/src/android/test/mock/MockContentResolver.java b/test-runner/src/android/test/mock/MockContentResolver.java
index 75c8335..d8e0977 100644
--- a/test-runner/src/android/test/mock/MockContentResolver.java
+++ b/test-runner/src/android/test/mock/MockContentResolver.java
@@ -49,12 +49,7 @@
* <p>For more information about application testing, read the
* <a href="{@docRoot}guide/topics/testing/index.html">Testing</a> developer guide.</p>
* </div>
- *
- * @deprecated Use a mocking framework like <a href="https://github.com/mockito/mockito">Mockito</a>.
- * New tests should be written using the
- * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
*/
-@Deprecated
public class MockContentResolver extends ContentResolver {
Map<String, ContentProvider> mProviders;
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index c7cbf97..b14fc41 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -55,12 +55,7 @@
* A mock {@link android.content.Context} class. All methods are non-functional and throw
* {@link java.lang.UnsupportedOperationException}. You can use this to inject other dependencies,
* mocks, or monitors into the classes you are testing.
- *
- * @deprecated Use a mocking framework like <a href="https://github.com/mockito/mockito">Mockito</a>.
- * New tests should be written using the
- * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
*/
-@Deprecated
public class MockContext extends Context {
@Override
diff --git a/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java b/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java
index f1ecc56..b9c5fac 100644
--- a/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java
@@ -19,8 +19,11 @@
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
@@ -31,37 +34,48 @@
* This should all be optimized out by the renderer.
*/
public class FullscreenOverdrawActivity extends AppCompatActivity {
- private class OverdrawView extends View {
+ private class OverdrawDrawable extends Drawable {
Paint paint = new Paint();
int mColorValue = 0;
- public OverdrawView(Context context) {
- super(context);
- }
-
@SuppressWarnings("unused")
public void setColorValue(int colorValue) {
mColorValue = colorValue;
- invalidate();
+ invalidateSelf();
}
@Override
- protected void onDraw(Canvas canvas) {
+ public void draw(Canvas canvas) {
paint.setColor(Color.rgb(mColorValue, 255 - mColorValue, 255));
for (int i = 0; i < 400; i++) {
- canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
+ canvas.drawRect(getBounds(), paint);
}
}
+
+ @Override
+ public void setAlpha(int alpha) {
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.OPAQUE;
+ }
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- OverdrawView overdrawView = new OverdrawView(this);
- setContentView(overdrawView);
+ OverdrawDrawable overdraw = new OverdrawDrawable();
+ getWindow().setBackgroundDrawable(overdraw);
- ObjectAnimator objectAnimator = ObjectAnimator.ofInt(overdrawView, "colorValue", 0, 255);
+ setContentView(new View(this));
+
+ ObjectAnimator objectAnimator = ObjectAnimator.ofInt(overdraw, "colorValue", 0, 255);
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
objectAnimator.start();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
index cbd0415..1afd90d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
@@ -23,6 +23,7 @@
import com.android.ide.common.rendering.api.StyleResourceValue;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.android.RenderParamsFlags;
import com.android.layoutlib.bridge.bars.AppCompatActionBar;
import com.android.layoutlib.bridge.bars.BridgeActionBar;
import com.android.layoutlib.bridge.bars.Config;
@@ -232,8 +233,10 @@
private BridgeActionBar createActionBar(@NonNull BridgeContext context,
@NonNull SessionParams params) {
+ boolean isMenu = "menu".equals(params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG));
+
BridgeActionBar actionBar;
- if (mBuilder.isThemeAppCompat()) {
+ if (mBuilder.isThemeAppCompat() && !isMenu) {
actionBar = new AppCompatActionBar(context, params);
} else {
actionBar = new FrameworkActionBar(context, params);