Merge "Fix badness from proxy refactoring."
diff --git a/Android.mk b/Android.mk
index 99d73fa..5e634c1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -76,8 +76,8 @@
core/java/android/app/ISearchManagerCallback.aidl \
core/java/android/app/IServiceConnection.aidl \
core/java/android/app/IStopUserCallback.aidl \
- core/java/android/app/task/ITaskCallback.aidl \
- core/java/android/app/task/ITaskService.aidl \
+ core/java/android/app/task/ITaskCallback.aidl \
+ core/java/android/app/task/ITaskService.aidl \
core/java/android/app/IThumbnailRetriever.aidl \
core/java/android/app/ITransientNotification.aidl \
core/java/android/app/IUiAutomationConnection.aidl \
diff --git a/api/current.txt b/api/current.txt
index 302e77e..9910fdf 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -250,7 +250,7 @@
field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4
field public static final int actionBarTabStyle = 16843507; // 0x10102f3
field public static final int actionBarTabTextStyle = 16843509; // 0x10102f5
- field public static final int actionBarTheme = 16843837; // 0x101043d
+ field public static final int actionBarTheme = 16843831; // 0x1010437
field public static final int actionBarWidgetTheme = 16843671; // 0x1010397
field public static final int actionButtonStyle = 16843480; // 0x10102d8
field public static final int actionDropDownStyle = 16843479; // 0x10102d7
@@ -267,7 +267,7 @@
field public static final int actionModeSplitBackground = 16843677; // 0x101039d
field public static final int actionModeStyle = 16843668; // 0x1010394
field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
- field public static final int actionOverflowMenuStyle = 16843857; // 0x1010451
+ field public static final int actionOverflowMenuStyle = 16843851; // 0x101044b
field public static final int actionProviderClass = 16843657; // 0x1010389
field public static final int actionViewClass = 16843516; // 0x10102fc
field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
@@ -295,7 +295,6 @@
field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
field public static final int alwaysRetainTaskState = 16843267; // 0x1010203
field public static final int angle = 16843168; // 0x10101a0
- field public static final int animate = 16843823; // 0x101042f
field public static final int animateFirstView = 16843477; // 0x10102d5
field public static final int animateLayoutChanges = 16843506; // 0x10102f2
field public static final int animateOnClick = 16843356; // 0x101025c
@@ -314,7 +313,7 @@
field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
field public static final int autoLink = 16842928; // 0x10100b0
field public static final int autoMirrored = 16843754; // 0x10103ea
- field public static final int autoRemoveFromRecents = 16843859; // 0x1010453
+ field public static final int autoRemoveFromRecents = 16843853; // 0x101044d
field public static final int autoStart = 16843445; // 0x10102b5
field public static final deprecated int autoText = 16843114; // 0x101016a
field public static final int autoUrlDetect = 16843404; // 0x101028c
@@ -383,29 +382,29 @@
field public static final int clipChildren = 16842986; // 0x10100ea
field public static final int clipOrientation = 16843274; // 0x101020a
field public static final int clipToPadding = 16842987; // 0x10100eb
- field public static final int clipToPath = 16843822; // 0x101042e
+ field public static final int clipToPath = 16843818; // 0x101042a
field public static final int codes = 16843330; // 0x1010242
field public static final int collapseColumns = 16843083; // 0x101014b
field public static final int color = 16843173; // 0x10101a5
- field public static final int colorAccent = 16843842; // 0x1010442
+ field public static final int colorAccent = 16843836; // 0x101043c
field public static final int colorActivatedHighlight = 16843664; // 0x1010390
field public static final int colorBackground = 16842801; // 0x1010031
field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
- field public static final int colorButtonNormal = 16843829; // 0x1010435
- field public static final int colorButtonNormalColored = 16843831; // 0x1010437
- field public static final int colorButtonPressed = 16843830; // 0x1010436
- field public static final int colorButtonPressedColored = 16843832; // 0x1010438
- field public static final int colorControlActivated = 16843828; // 0x1010434
- field public static final int colorControlNormal = 16843827; // 0x1010433
+ field public static final int colorButtonNormal = 16843823; // 0x101042f
+ field public static final int colorButtonNormalColored = 16843825; // 0x1010431
+ field public static final int colorButtonPressed = 16843824; // 0x1010430
+ field public static final int colorButtonPressedColored = 16843826; // 0x1010432
+ field public static final int colorControlActivated = 16843822; // 0x101042e
+ field public static final int colorControlNormal = 16843821; // 0x101042d
field public static final int colorFocusedHighlight = 16843663; // 0x101038f
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
field public static final int colorLongPressedHighlight = 16843662; // 0x101038e
field public static final int colorMultiSelectHighlight = 16843665; // 0x1010391
field public static final int colorPressedHighlight = 16843661; // 0x101038d
- field public static final int colorPrimary = 16843840; // 0x1010440
- field public static final int colorPrimaryDark = 16843841; // 0x1010441
- field public static final int colorPrimaryLight = 16843839; // 0x101043f
+ field public static final int colorPrimary = 16843834; // 0x101043a
+ field public static final int colorPrimaryDark = 16843835; // 0x101043b
+ field public static final int colorPrimaryLight = 16843833; // 0x1010439
field public static final int columnCount = 16843639; // 0x1010377
field public static final int columnDelay = 16843215; // 0x10101cf
field public static final int columnOrderPreserved = 16843640; // 0x1010378
@@ -464,7 +463,7 @@
field public static final int dividerHorizontal = 16843564; // 0x101032c
field public static final int dividerPadding = 16843562; // 0x101032a
field public static final int dividerVertical = 16843530; // 0x101030a
- field public static final int documentLaunchMode = 16843858; // 0x1010452
+ field public static final int documentLaunchMode = 16843852; // 0x101044c
field public static final int drawSelectorOnTop = 16843004; // 0x10100fc
field public static final int drawable = 16843161; // 0x1010199
field public static final int drawableBottom = 16843118; // 0x101016e
@@ -487,14 +486,13 @@
field public static final int dropDownWidth = 16843362; // 0x1010262
field public static final int duplicateParentState = 16842985; // 0x10100e9
field public static final int duration = 16843160; // 0x1010198
- field public static final int durations = 16843814; // 0x1010426
field public static final int editTextBackground = 16843602; // 0x1010352
field public static final int editTextColor = 16843601; // 0x1010351
field public static final int editTextPreferenceStyle = 16842898; // 0x1010092
field public static final int editTextStyle = 16842862; // 0x101006e
field public static final deprecated int editable = 16843115; // 0x101016b
field public static final int editorExtras = 16843300; // 0x1010224
- field public static final int elevation = 16843853; // 0x101044d
+ field public static final int elevation = 16843847; // 0x1010447
field public static final int ellipsize = 16842923; // 0x10100ab
field public static final int ems = 16843096; // 0x1010158
field public static final int enabled = 16842766; // 0x101000e
@@ -504,9 +502,9 @@
field public static final int entries = 16842930; // 0x10100b2
field public static final int entryValues = 16843256; // 0x10101f8
field public static final int eventsInterceptionEnabled = 16843389; // 0x101027d
- field public static final int excludeClass = 16843855; // 0x101044f
+ field public static final int excludeClass = 16843849; // 0x1010449
field public static final int excludeFromRecents = 16842775; // 0x1010017
- field public static final int excludeId = 16843854; // 0x101044e
+ field public static final int excludeId = 16843848; // 0x1010448
field public static final int exitFadeDuration = 16843533; // 0x101030d
field public static final int expandableListPreferredChildIndicatorLeft = 16842834; // 0x1010052
field public static final int expandableListPreferredChildIndicatorRight = 16842835; // 0x1010053
@@ -535,11 +533,11 @@
field public static final int fastScrollTextColor = 16843609; // 0x1010359
field public static final int fastScrollThumbDrawable = 16843574; // 0x1010336
field public static final int fastScrollTrackDrawable = 16843577; // 0x1010339
- field public static final int fill = 16843809; // 0x1010421
+ field public static final int fill = 16843808; // 0x1010420
field public static final int fillAfter = 16843197; // 0x10101bd
field public static final int fillBefore = 16843196; // 0x10101bc
field public static final int fillEnabled = 16843343; // 0x101024f
- field public static final int fillOpacity = 16843808; // 0x1010420
+ field public static final int fillOpacity = 16843807; // 0x101041f
field public static final int fillViewport = 16843130; // 0x101017a
field public static final int filter = 16843035; // 0x101011b
field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -601,7 +599,7 @@
field public static final int headerBackground = 16843055; // 0x101012f
field public static final int headerDividersEnabled = 16843310; // 0x101022e
field public static final int height = 16843093; // 0x1010155
- field public static final int hideOnContentScroll = 16843856; // 0x1010450
+ field public static final int hideOnContentScroll = 16843850; // 0x101044a
field public static final int hint = 16843088; // 0x1010150
field public static final int homeAsUpIndicator = 16843531; // 0x101030b
field public static final int homeLayout = 16843549; // 0x101031d
@@ -771,7 +769,6 @@
field public static final int layout_x = 16843135; // 0x101017f
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
- field public static final int limitTo = 16843824; // 0x1010430
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 +830,7 @@
field public static final int name = 16842755; // 0x1010003
field public static final int navigationMode = 16843471; // 0x10102cf
field public static final int negativeButtonText = 16843254; // 0x10101f6
- field public static final int nestedScrollingEnabled = 16843843; // 0x1010443
+ field public static final int nestedScrollingEnabled = 16843837; // 0x101043d
field public static final int nextFocusDown = 16842980; // 0x10100e4
field public static final int nextFocusForward = 16843580; // 0x101033c
field public static final int nextFocusLeft = 16842977; // 0x10100e1
@@ -875,18 +872,18 @@
field public static final int parentActivityName = 16843687; // 0x10103a7
field public static final deprecated int password = 16843100; // 0x101015c
field public static final int path = 16842794; // 0x101002a
- field public static final int pathData = 16843810; // 0x1010422
+ field public static final int pathData = 16843809; // 0x1010421
field public static final int pathPattern = 16842796; // 0x101002c
field public static final int pathPrefix = 16842795; // 0x101002b
field public static final int permission = 16842758; // 0x1010006
field public static final int permissionFlags = 16843719; // 0x10103c7
field public static final int permissionGroup = 16842762; // 0x101000a
field public static final int permissionGroupFlags = 16843717; // 0x10103c5
- field public static final int persistable = 16843833; // 0x1010439
+ field public static final int persistable = 16843827; // 0x1010433
field public static final int persistent = 16842765; // 0x101000d
field public static final int persistentDrawingCache = 16842990; // 0x10100ee
field public static final deprecated int phoneNumber = 16843111; // 0x1010167
- field public static final int pinned = 16843826; // 0x1010432
+ field public static final int pinned = 16843820; // 0x101042c
field public static final int pivotX = 16843189; // 0x10101b5
field public static final int pivotY = 16843190; // 0x10101b6
field public static final int popupAnimationStyle = 16843465; // 0x10102c9
@@ -941,7 +938,6 @@
field public static final int readPermission = 16842759; // 0x1010007
field public static final int repeatCount = 16843199; // 0x10101bf
field public static final int repeatMode = 16843200; // 0x10101c0
- field public static final int repeatStyle = 16843816; // 0x1010428
field public static final int reqFiveWayNav = 16843314; // 0x1010232
field public static final int reqHardKeyboard = 16843305; // 0x1010229
field public static final int reqKeyboardType = 16843304; // 0x1010228
@@ -951,7 +947,7 @@
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
- field public static final int requiredForProfile = 16843825; // 0x1010431
+ field public static final int requiredForProfile = 16843819; // 0x101042b
field public static final int requiresFadingEdge = 16843685; // 0x10103a5
field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
field public static final int resizeMode = 16843619; // 0x1010363
@@ -1015,8 +1011,7 @@
field public static final int selectableItemBackground = 16843534; // 0x101030e
field public static final int selectedDateVerticalBar = 16843591; // 0x1010347
field public static final int selectedWeekBackgroundColor = 16843586; // 0x1010342
- field public static final int sequence = 16843815; // 0x1010427
- field public static final int sessionService = 16843850; // 0x101044a
+ field public static final int sessionService = 16843844; // 0x1010444
field public static final int settingsActivity = 16843301; // 0x1010225
field public static final int shadowColor = 16843105; // 0x1010161
field public static final int shadowDx = 16843106; // 0x1010162
@@ -1038,7 +1033,7 @@
field public static final int shrinkColumns = 16843082; // 0x101014a
field public static final deprecated int singleLine = 16843101; // 0x101015d
field public static final int singleUser = 16843711; // 0x10103bf
- field public static final int slideEdge = 16843836; // 0x101043c
+ field public static final int slideEdge = 16843830; // 0x1010436
field public static final int smallIcon = 16843422; // 0x101029e
field public static final int smallScreens = 16843396; // 0x1010284
field public static final int smoothScrollbar = 16843313; // 0x1010231
@@ -1055,13 +1050,13 @@
field public static final int sspPattern = 16843749; // 0x10103e5
field public static final int sspPrefix = 16843748; // 0x10103e4
field public static final int stackFromBottom = 16843005; // 0x10100fd
- field public static final int stackViewStyle = 16843851; // 0x101044b
+ field public static final int stackViewStyle = 16843845; // 0x1010445
field public static final int starStyle = 16842882; // 0x1010082
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 deprecated int startYear = 16843132; // 0x101017c
- field public static final int stateListAnimator = 16843860; // 0x1010454
+ field public static final int stateListAnimator = 16843854; // 0x101044e
field public static final int stateNotNeeded = 16842774; // 0x1010016
field public static final int state_above_anchor = 16842922; // 0x10100aa
field public static final int state_accelerated = 16843547; // 0x101031b
@@ -1091,13 +1086,13 @@
field public static final int streamType = 16843273; // 0x1010209
field public static final int stretchColumns = 16843081; // 0x1010149
field public static final int stretchMode = 16843030; // 0x1010116
- field public static final int stroke = 16843811; // 0x1010423
- field public static final int strokeLineCap = 16843820; // 0x101042c
- field public static final int strokeLineJoin = 16843821; // 0x101042d
- field public static final int strokeOpacity = 16843812; // 0x1010424
- field public static final int strokeWidth = 16843813; // 0x1010425
+ field public static final int stroke = 16843810; // 0x1010422
+ field public static final int strokeLineCap = 16843816; // 0x1010428
+ field public static final int strokeLineJoin = 16843817; // 0x1010429
+ field public static final int strokeOpacity = 16843811; // 0x1010423
+ field public static final int strokeWidth = 16843812; // 0x1010424
field public static final int subtitle = 16843473; // 0x10102d1
- field public static final int subtitleTextAppearance = 16843835; // 0x101043b
+ field public static final int subtitleTextAppearance = 16843829; // 0x1010435
field public static final int subtitleTextStyle = 16843513; // 0x10102f9
field public static final int subtypeExtraValue = 16843674; // 0x101039a
field public static final int subtypeId = 16843713; // 0x10103c1
@@ -1114,7 +1109,7 @@
field public static final int switchMinWidth = 16843632; // 0x1010370
field public static final int switchPadding = 16843633; // 0x1010371
field public static final int switchPreferenceStyle = 16843629; // 0x101036d
- field public static final int switchStyle = 16843852; // 0x101044c
+ field public static final int switchStyle = 16843846; // 0x1010446
field public static final int switchTextAppearance = 16843630; // 0x101036e
field public static final int switchTextOff = 16843628; // 0x101036c
field public static final int switchTextOn = 16843627; // 0x101036b
@@ -1151,7 +1146,7 @@
field public static final int textAppearanceLargeInverse = 16842819; // 0x1010043
field public static final int textAppearanceLargePopupMenu = 16843521; // 0x1010301
field public static final int textAppearanceListItem = 16843678; // 0x101039e
- field public static final int textAppearanceListItemSecondary = 16843838; // 0x101043e
+ field public static final int textAppearanceListItemSecondary = 16843832; // 0x1010438
field public static final int textAppearanceListItemSmall = 16843679; // 0x101039f
field public static final int textAppearanceMedium = 16842817; // 0x1010041
field public static final int textAppearanceMediumInverse = 16842820; // 0x1010044
@@ -1215,7 +1210,7 @@
field public static final int tintMode = 16843798; // 0x1010416
field public static final int title = 16843233; // 0x10101e1
field public static final int titleCondensed = 16843234; // 0x10101e2
- field public static final int titleTextAppearance = 16843834; // 0x101043a
+ field public static final int titleTextAppearance = 16843828; // 0x1010434
field public static final int titleTextStyle = 16843512; // 0x10102f8
field public static final int toAlpha = 16843211; // 0x10101cb
field public static final int toDegrees = 16843188; // 0x10101b4
@@ -1240,10 +1235,9 @@
field public static final int translationX = 16843554; // 0x1010322
field public static final int translationY = 16843555; // 0x1010323
field public static final int translationZ = 16843797; // 0x1010415
- field public static final int trigger = 16843805; // 0x101041d
- field public static final int trimPathEnd = 16843818; // 0x101042a
- field public static final int trimPathOffset = 16843819; // 0x101042b
- field public static final int trimPathStart = 16843817; // 0x1010429
+ field public static final int trimPathEnd = 16843814; // 0x1010426
+ field public static final int trimPathOffset = 16843815; // 0x1010427
+ field public static final int trimPathStart = 16843813; // 0x1010425
field public static final int type = 16843169; // 0x10101a1
field public static final int typeface = 16842902; // 0x1010096
field public static final int uiOptions = 16843672; // 0x1010398
@@ -1268,8 +1262,8 @@
field public static final int verticalGap = 16843328; // 0x1010240
field public static final int verticalScrollbarPosition = 16843572; // 0x1010334
field public static final int verticalSpacing = 16843029; // 0x1010115
- field public static final int viewportHeight = 16843807; // 0x101041f
- field public static final int viewportWidth = 16843806; // 0x101041e
+ field public static final int viewportHeight = 16843806; // 0x101041e
+ field public static final int viewportWidth = 16843805; // 0x101041d
field public static final int visibility = 16842972; // 0x10100dc
field public static final int visible = 16843156; // 0x1010194
field public static final int vmSafeMode = 16843448; // 0x10102b8
@@ -1298,8 +1292,8 @@
field public static final int windowActionBar = 16843469; // 0x10102cd
field public static final int windowActionBarOverlay = 16843492; // 0x10102e4
field public static final int windowActionModeOverlay = 16843485; // 0x10102dd
- field public static final int windowAllowEnterTransitionOverlap = 16843849; // 0x1010449
- field public static final int windowAllowExitTransitionOverlap = 16843848; // 0x1010448
+ field public static final int windowAllowEnterTransitionOverlap = 16843843; // 0x1010443
+ field public static final int windowAllowExitTransitionOverlap = 16843842; // 0x1010442
field public static final int windowAnimationStyle = 16842926; // 0x10100ae
field public static final int windowBackground = 16842836; // 0x1010054
field public static final int windowCloseOnTouchOutside = 16843611; // 0x101035b
@@ -1309,9 +1303,9 @@
field public static final int windowDisablePreview = 16843298; // 0x1010222
field public static final int windowEnableSplitTouch = 16843543; // 0x1010317
field public static final int windowEnterAnimation = 16842932; // 0x10100b4
- field public static final int windowEnterTransition = 16843844; // 0x1010444
+ field public static final int windowEnterTransition = 16843838; // 0x101043e
field public static final int windowExitAnimation = 16842933; // 0x10100b5
- field public static final int windowExitTransition = 16843845; // 0x1010445
+ field public static final int windowExitTransition = 16843839; // 0x101043f
field public static final int windowFrame = 16842837; // 0x1010055
field public static final int windowFullscreen = 16843277; // 0x101020d
field public static final int windowHideAnimation = 16842935; // 0x10100b7
@@ -1322,8 +1316,8 @@
field public static final int windowNoDisplay = 16843294; // 0x101021e
field public static final int windowNoTitle = 16842838; // 0x1010056
field public static final int windowOverscan = 16843727; // 0x10103cf
- field public static final int windowSharedElementEnterTransition = 16843846; // 0x1010446
- field public static final int windowSharedElementExitTransition = 16843847; // 0x1010447
+ field public static final int windowSharedElementEnterTransition = 16843840; // 0x1010440
+ field public static final int windowSharedElementExitTransition = 16843841; // 0x1010441
field public static final int windowShowAnimation = 16842934; // 0x10100b6
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
@@ -5056,6 +5050,7 @@
method public boolean isActivePasswordSufficient();
method public boolean isAdminActive(android.content.ComponentName);
method public boolean isDeviceOwnerApp(java.lang.String);
+ method public boolean isLockTaskPermitted(android.content.ComponentName);
method public boolean isProfileOwnerApp(java.lang.String);
method public void lockNow();
method public void removeActiveAdmin(android.content.ComponentName);
@@ -5064,6 +5059,7 @@
method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
method public void setCameraDisabled(android.content.ComponentName, boolean);
method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
+ method public void setLockTaskComponents(android.content.ComponentName[]) throws java.lang.SecurityException;
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
method public void setMaximumTimeToLock(android.content.ComponentName, long);
method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
@@ -8053,6 +8049,7 @@
field public static final java.lang.String FEATURE_CAMERA = "android.hardware.camera";
field public static final java.lang.String FEATURE_CAMERA_ANY = "android.hardware.camera.any";
field public static final java.lang.String FEATURE_CAMERA_AUTOFOCUS = "android.hardware.camera.autofocus";
+ field public static final java.lang.String FEATURE_CAMERA_EXTERNAL = "android.hardware.camera.external";
field public static final java.lang.String FEATURE_CAMERA_FLASH = "android.hardware.camera.flash";
field public static final java.lang.String FEATURE_CAMERA_FRONT = "android.hardware.camera.front";
field public static final java.lang.String FEATURE_CONSUMER_IR = "android.hardware.consumerir";
@@ -12873,6 +12870,7 @@
method public void onStartInputView(android.view.inputmethod.EditorInfo, boolean);
method public void onUnbindInput();
method public void onUpdateCursor(android.graphics.Rect);
+ method public void onUpdateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo);
method public void onUpdateExtractedText(int, android.view.inputmethod.ExtractedText);
method public void onUpdateExtractingViews(android.view.inputmethod.EditorInfo);
method public void onUpdateExtractingVisibility(android.view.inputmethod.EditorInfo);
@@ -12922,6 +12920,7 @@
method public void finishInput();
method public void toggleSoftInput(int, int);
method public void updateCursor(android.graphics.Rect);
+ method public void updateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo);
method public void updateExtractedText(int, android.view.inputmethod.ExtractedText);
method public void updateSelection(int, int, int, int, int, int);
method public void viewClicked(boolean);
@@ -13584,6 +13583,7 @@
method public void stop() throws java.lang.IllegalStateException;
method public int write(byte[], int, int);
method public int write(short[], int, int);
+ method public int write(java.nio.ByteBuffer, int, int);
field public static final int ERROR = -1; // 0xffffffff
field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
@@ -13596,6 +13596,8 @@
field public static final int STATE_NO_STATIC_DATA = 2; // 0x2
field public static final int STATE_UNINITIALIZED = 0; // 0x0
field public static final int SUCCESS = 0; // 0x0
+ field public static final int WRITE_BLOCKING = 0; // 0x0
+ field public static final int WRITE_NON_BLOCKING = 1; // 0x1
}
public static abstract interface AudioTrack.OnPlaybackPositionUpdateListener {
@@ -17136,6 +17138,7 @@
}
public final class CardEmulation {
+ method public boolean categoryAllowsForegroundPreference(java.lang.String);
method public android.nfc.cardemulation.AidGroup getAidGroupForService(android.content.ComponentName, java.lang.String);
method public static synchronized android.nfc.cardemulation.CardEmulation getInstance(android.nfc.NfcAdapter);
method public int getSelectionModeForCategory(java.lang.String);
@@ -17143,6 +17146,8 @@
method public boolean isDefaultServiceForCategory(android.content.ComponentName, java.lang.String);
method public boolean registerAidGroupForService(android.content.ComponentName, android.nfc.cardemulation.AidGroup);
method public boolean removeAidGroupForService(android.content.ComponentName, java.lang.String);
+ method public boolean setPreferredService(android.app.Activity, android.content.ComponentName);
+ method public boolean unsetPreferredService(android.app.Activity);
field public static final java.lang.String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
field public static final java.lang.String CATEGORY_OTHER = "other";
field public static final java.lang.String CATEGORY_PAYMENT = "payment";
@@ -20549,6 +20554,7 @@
method public void setUserRestrictions(android.os.Bundle);
method public void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user";
+ field public static final java.lang.String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
field public static final java.lang.String DISALLOW_CONFIG_APPS = "no_config_apps";
field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
@@ -20562,9 +20568,11 @@
field public static final java.lang.String DISALLOW_INSTALL_APPS = "no_install_apps";
field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
+ field public static final java.lang.String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
+ field public static final java.lang.String DISALLOW_UNMUTE_MICROPHONE = "no_unmute_microphone";
field public static final java.lang.String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
field public static final java.lang.String ENSURE_VERIFY_APPS = "ensure_verify_apps";
}
@@ -25716,6 +25724,636 @@
}
+package android.system {
+
+ public final class ErrnoException extends java.lang.Exception {
+ ctor public ErrnoException(java.lang.String, int);
+ ctor public ErrnoException(java.lang.String, int, java.lang.Throwable);
+ field public final int errno;
+ }
+
+ public final class Os {
+ method public static java.io.FileDescriptor accept(java.io.FileDescriptor, java.net.InetSocketAddress) throws android.system.ErrnoException, java.net.SocketException;
+ method public static boolean access(java.lang.String, int) throws android.system.ErrnoException;
+ method public static void bind(java.io.FileDescriptor, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
+ method public static void chmod(java.lang.String, int) throws android.system.ErrnoException;
+ method public static void chown(java.lang.String, int, int) throws android.system.ErrnoException;
+ method public static void close(java.io.FileDescriptor) throws android.system.ErrnoException;
+ method public static void connect(java.io.FileDescriptor, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
+ method public static java.io.FileDescriptor dup(java.io.FileDescriptor) throws android.system.ErrnoException;
+ method public static java.io.FileDescriptor dup2(java.io.FileDescriptor, int) throws android.system.ErrnoException;
+ method public static java.lang.String[] environ();
+ method public static void execv(java.lang.String, java.lang.String[]) throws android.system.ErrnoException;
+ method public static void execve(java.lang.String, java.lang.String[], java.lang.String[]) throws android.system.ErrnoException;
+ method public static void fchmod(java.io.FileDescriptor, int) throws android.system.ErrnoException;
+ method public static void fchown(java.io.FileDescriptor, int, int) throws android.system.ErrnoException;
+ method public static void fdatasync(java.io.FileDescriptor) throws android.system.ErrnoException;
+ method public static android.system.StructStat fstat(java.io.FileDescriptor) throws android.system.ErrnoException;
+ method public static android.system.StructStatVfs fstatvfs(java.io.FileDescriptor) throws android.system.ErrnoException;
+ method public static void fsync(java.io.FileDescriptor) throws android.system.ErrnoException;
+ method public static void ftruncate(java.io.FileDescriptor, long) throws android.system.ErrnoException;
+ method public static java.lang.String gai_strerror(int);
+ method public static int getegid();
+ method public static java.lang.String getenv(java.lang.String);
+ method public static int geteuid();
+ method public static int getgid();
+ method public static java.net.SocketAddress getpeername(java.io.FileDescriptor) throws android.system.ErrnoException;
+ method public static int getpid();
+ method public static int getppid();
+ method public static java.net.SocketAddress getsockname(java.io.FileDescriptor) throws android.system.ErrnoException;
+ method public static int gettid();
+ method public static int getuid();
+ method public static java.lang.String if_indextoname(int);
+ method public static java.net.InetAddress inet_pton(int, java.lang.String);
+ method public static boolean isatty(java.io.FileDescriptor);
+ method public static void kill(int, int) throws android.system.ErrnoException;
+ method public static void lchown(java.lang.String, int, int) throws android.system.ErrnoException;
+ method public static void listen(java.io.FileDescriptor, int) throws android.system.ErrnoException;
+ method public static long lseek(java.io.FileDescriptor, long, int) throws android.system.ErrnoException;
+ method public static android.system.StructStat lstat(java.lang.String) throws android.system.ErrnoException;
+ method public static void mincore(long, long, byte[]) throws android.system.ErrnoException;
+ method public static void mkdir(java.lang.String, int) throws android.system.ErrnoException;
+ method public static void mkfifo(java.lang.String, int) throws android.system.ErrnoException;
+ method public static void mlock(long, long) throws android.system.ErrnoException;
+ method public static long mmap(long, long, int, int, java.io.FileDescriptor, long) throws android.system.ErrnoException;
+ method public static void msync(long, long, int) throws android.system.ErrnoException;
+ method public static void munlock(long, long) throws android.system.ErrnoException;
+ method public static void munmap(long, long) throws android.system.ErrnoException;
+ method public static java.io.FileDescriptor open(java.lang.String, int, int) throws android.system.ErrnoException;
+ method public static java.io.FileDescriptor[] pipe() throws android.system.ErrnoException;
+ method public static int poll(android.system.StructPollfd[], int) throws android.system.ErrnoException;
+ method public static void posix_fallocate(java.io.FileDescriptor, long, long) throws android.system.ErrnoException;
+ method public static int prctl(int, long, long, long, long) throws android.system.ErrnoException;
+ method public static int pread(java.io.FileDescriptor, java.nio.ByteBuffer, long) throws android.system.ErrnoException, java.io.InterruptedIOException;
+ method public static int pread(java.io.FileDescriptor, byte[], int, int, long) throws android.system.ErrnoException, java.io.InterruptedIOException;
+ method public static int pwrite(java.io.FileDescriptor, java.nio.ByteBuffer, long) throws android.system.ErrnoException, java.io.InterruptedIOException;
+ method public static int pwrite(java.io.FileDescriptor, byte[], int, int, long) throws android.system.ErrnoException, java.io.InterruptedIOException;
+ method public static int read(java.io.FileDescriptor, java.nio.ByteBuffer) throws android.system.ErrnoException, java.io.InterruptedIOException;
+ method public static int read(java.io.FileDescriptor, byte[], int, int) throws android.system.ErrnoException, java.io.InterruptedIOException;
+ method public static java.lang.String readlink(java.lang.String) throws android.system.ErrnoException;
+ method public static int readv(java.io.FileDescriptor, java.lang.Object[], int[], int[]) throws android.system.ErrnoException, java.io.InterruptedIOException;
+ method public static int recvfrom(java.io.FileDescriptor, java.nio.ByteBuffer, int, java.net.InetSocketAddress) throws android.system.ErrnoException, java.net.SocketException;
+ method public static int recvfrom(java.io.FileDescriptor, byte[], int, int, int, java.net.InetSocketAddress) throws android.system.ErrnoException, java.net.SocketException;
+ method public static void remove(java.lang.String) throws android.system.ErrnoException;
+ method public static void rename(java.lang.String, java.lang.String) throws android.system.ErrnoException;
+ method public static long sendfile(java.io.FileDescriptor, java.io.FileDescriptor, android.util.MutableLong, long) throws android.system.ErrnoException;
+ method public static int sendto(java.io.FileDescriptor, java.nio.ByteBuffer, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
+ method public static int sendto(java.io.FileDescriptor, byte[], int, int, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
+ method public static void setegid(int) throws android.system.ErrnoException;
+ method public static void setenv(java.lang.String, java.lang.String, boolean) throws android.system.ErrnoException;
+ method public static void seteuid(int) throws android.system.ErrnoException;
+ method public static void setgid(int) throws android.system.ErrnoException;
+ method public static int setsid() throws android.system.ErrnoException;
+ method public static void setuid(int) throws android.system.ErrnoException;
+ method public static void shutdown(java.io.FileDescriptor, int) throws android.system.ErrnoException;
+ method public static java.io.FileDescriptor socket(int, int, int) throws android.system.ErrnoException;
+ method public static void socketpair(int, int, int, java.io.FileDescriptor, java.io.FileDescriptor) throws android.system.ErrnoException;
+ method public static android.system.StructStat stat(java.lang.String) throws android.system.ErrnoException;
+ method public static android.system.StructStatVfs statvfs(java.lang.String) throws android.system.ErrnoException;
+ method public static java.lang.String strerror(int);
+ method public static java.lang.String strsignal(int);
+ method public static void symlink(java.lang.String, java.lang.String) throws android.system.ErrnoException;
+ method public static long sysconf(int);
+ method public static void tcdrain(java.io.FileDescriptor) throws android.system.ErrnoException;
+ method public static void tcsendbreak(java.io.FileDescriptor, int) throws android.system.ErrnoException;
+ method public static int umask(int);
+ method public static android.system.StructUtsname uname();
+ method public static void unsetenv(java.lang.String) throws android.system.ErrnoException;
+ method public static int waitpid(int, android.util.MutableInt, int) throws android.system.ErrnoException;
+ method public static int write(java.io.FileDescriptor, java.nio.ByteBuffer) throws android.system.ErrnoException, java.io.InterruptedIOException;
+ method public static int write(java.io.FileDescriptor, byte[], int, int) throws android.system.ErrnoException, java.io.InterruptedIOException;
+ method public static int writev(java.io.FileDescriptor, java.lang.Object[], int[], int[]) throws android.system.ErrnoException, java.io.InterruptedIOException;
+ }
+
+ public final class OsConstants {
+ method public static boolean S_ISBLK(int);
+ method public static boolean S_ISCHR(int);
+ method public static boolean S_ISDIR(int);
+ method public static boolean S_ISFIFO(int);
+ method public static boolean S_ISLNK(int);
+ method public static boolean S_ISREG(int);
+ method public static boolean S_ISSOCK(int);
+ method public static boolean WCOREDUMP(int);
+ method public static int WEXITSTATUS(int);
+ method public static boolean WIFEXITED(int);
+ method public static boolean WIFSIGNALED(int);
+ method public static boolean WIFSTOPPED(int);
+ method public static int WSTOPSIG(int);
+ method public static int WTERMSIG(int);
+ method public static java.lang.String errnoName(int);
+ method public static java.lang.String gaiName(int);
+ field public static final int AF_INET;
+ field public static final int AF_INET6;
+ field public static final int AF_UNIX;
+ field public static final int AF_UNSPEC;
+ field public static final int AI_ADDRCONFIG;
+ field public static final int AI_ALL;
+ field public static final int AI_CANONNAME;
+ field public static final int AI_NUMERICHOST;
+ field public static final int AI_NUMERICSERV;
+ field public static final int AI_PASSIVE;
+ field public static final int AI_V4MAPPED;
+ field public static final int CAP_AUDIT_CONTROL;
+ field public static final int CAP_AUDIT_WRITE;
+ field public static final int CAP_BLOCK_SUSPEND;
+ field public static final int CAP_CHOWN;
+ field public static final int CAP_DAC_OVERRIDE;
+ field public static final int CAP_DAC_READ_SEARCH;
+ field public static final int CAP_FOWNER;
+ field public static final int CAP_FSETID;
+ field public static final int CAP_IPC_LOCK;
+ field public static final int CAP_IPC_OWNER;
+ field public static final int CAP_KILL;
+ field public static final int CAP_LAST_CAP;
+ field public static final int CAP_LEASE;
+ field public static final int CAP_LINUX_IMMUTABLE;
+ field public static final int CAP_MAC_ADMIN;
+ field public static final int CAP_MAC_OVERRIDE;
+ field public static final int CAP_MKNOD;
+ field public static final int CAP_NET_ADMIN;
+ field public static final int CAP_NET_BIND_SERVICE;
+ field public static final int CAP_NET_BROADCAST;
+ field public static final int CAP_NET_RAW;
+ field public static final int CAP_SETFCAP;
+ field public static final int CAP_SETGID;
+ field public static final int CAP_SETPCAP;
+ field public static final int CAP_SETUID;
+ field public static final int CAP_SYSLOG;
+ field public static final int CAP_SYS_ADMIN;
+ field public static final int CAP_SYS_BOOT;
+ field public static final int CAP_SYS_CHROOT;
+ field public static final int CAP_SYS_MODULE;
+ field public static final int CAP_SYS_NICE;
+ field public static final int CAP_SYS_PACCT;
+ field public static final int CAP_SYS_PTRACE;
+ field public static final int CAP_SYS_RAWIO;
+ field public static final int CAP_SYS_RESOURCE;
+ field public static final int CAP_SYS_TIME;
+ field public static final int CAP_SYS_TTY_CONFIG;
+ field public static final int CAP_WAKE_ALARM;
+ field public static final int E2BIG;
+ field public static final int EACCES;
+ field public static final int EADDRINUSE;
+ field public static final int EADDRNOTAVAIL;
+ field public static final int EAFNOSUPPORT;
+ field public static final int EAGAIN;
+ field public static final int EAI_AGAIN;
+ field public static final int EAI_BADFLAGS;
+ field public static final int EAI_FAIL;
+ field public static final int EAI_FAMILY;
+ field public static final int EAI_MEMORY;
+ field public static final int EAI_NODATA;
+ field public static final int EAI_NONAME;
+ field public static final int EAI_OVERFLOW;
+ field public static final int EAI_SERVICE;
+ field public static final int EAI_SOCKTYPE;
+ field public static final int EAI_SYSTEM;
+ field public static final int EALREADY;
+ field public static final int EBADF;
+ field public static final int EBADMSG;
+ field public static final int EBUSY;
+ field public static final int ECANCELED;
+ field public static final int ECHILD;
+ field public static final int ECONNABORTED;
+ field public static final int ECONNREFUSED;
+ field public static final int ECONNRESET;
+ field public static final int EDEADLK;
+ field public static final int EDESTADDRREQ;
+ field public static final int EDOM;
+ field public static final int EDQUOT;
+ field public static final int EEXIST;
+ field public static final int EFAULT;
+ field public static final int EFBIG;
+ field public static final int EHOSTUNREACH;
+ field public static final int EIDRM;
+ field public static final int EILSEQ;
+ field public static final int EINPROGRESS;
+ field public static final int EINTR;
+ field public static final int EINVAL;
+ field public static final int EIO;
+ field public static final int EISCONN;
+ field public static final int EISDIR;
+ field public static final int ELOOP;
+ field public static final int EMFILE;
+ field public static final int EMLINK;
+ field public static final int EMSGSIZE;
+ field public static final int EMULTIHOP;
+ field public static final int ENAMETOOLONG;
+ field public static final int ENETDOWN;
+ field public static final int ENETRESET;
+ field public static final int ENETUNREACH;
+ field public static final int ENFILE;
+ field public static final int ENOBUFS;
+ field public static final int ENODATA;
+ field public static final int ENODEV;
+ field public static final int ENOENT;
+ field public static final int ENOEXEC;
+ field public static final int ENOLCK;
+ field public static final int ENOLINK;
+ field public static final int ENOMEM;
+ field public static final int ENOMSG;
+ field public static final int ENOPROTOOPT;
+ field public static final int ENOSPC;
+ field public static final int ENOSR;
+ field public static final int ENOSTR;
+ field public static final int ENOSYS;
+ field public static final int ENOTCONN;
+ field public static final int ENOTDIR;
+ field public static final int ENOTEMPTY;
+ field public static final int ENOTSOCK;
+ field public static final int ENOTSUP;
+ field public static final int ENOTTY;
+ field public static final int ENXIO;
+ field public static final int EOPNOTSUPP;
+ field public static final int EOVERFLOW;
+ field public static final int EPERM;
+ field public static final int EPIPE;
+ field public static final int EPROTO;
+ field public static final int EPROTONOSUPPORT;
+ field public static final int EPROTOTYPE;
+ field public static final int ERANGE;
+ field public static final int EROFS;
+ field public static final int ESPIPE;
+ field public static final int ESRCH;
+ field public static final int ESTALE;
+ field public static final int ETIME;
+ field public static final int ETIMEDOUT;
+ field public static final int ETXTBSY;
+ field public static final int EXDEV;
+ field public static final int EXIT_FAILURE;
+ field public static final int EXIT_SUCCESS;
+ field public static final int FD_CLOEXEC;
+ field public static final int FIONREAD;
+ field public static final int F_DUPFD;
+ field public static final int F_GETFD;
+ field public static final int F_GETFL;
+ field public static final int F_GETLK;
+ field public static final int F_GETLK64;
+ field public static final int F_GETOWN;
+ field public static final int F_OK;
+ field public static final int F_RDLCK;
+ field public static final int F_SETFD;
+ field public static final int F_SETFL;
+ field public static final int F_SETLK;
+ field public static final int F_SETLK64;
+ field public static final int F_SETLKW;
+ field public static final int F_SETLKW64;
+ field public static final int F_SETOWN;
+ field public static final int F_UNLCK;
+ field public static final int F_WRLCK;
+ field public static final int IFA_F_DADFAILED;
+ field public static final int IFA_F_DEPRECATED;
+ field public static final int IFA_F_HOMEADDRESS;
+ field public static final int IFA_F_NODAD;
+ field public static final int IFA_F_OPTIMISTIC;
+ field public static final int IFA_F_PERMANENT;
+ field public static final int IFA_F_SECONDARY;
+ field public static final int IFA_F_TEMPORARY;
+ field public static final int IFA_F_TENTATIVE;
+ field public static final int IFF_ALLMULTI;
+ field public static final int IFF_AUTOMEDIA;
+ field public static final int IFF_BROADCAST;
+ field public static final int IFF_DEBUG;
+ field public static final int IFF_DYNAMIC;
+ field public static final int IFF_LOOPBACK;
+ field public static final int IFF_MASTER;
+ field public static final int IFF_MULTICAST;
+ field public static final int IFF_NOARP;
+ field public static final int IFF_NOTRAILERS;
+ field public static final int IFF_POINTOPOINT;
+ field public static final int IFF_PORTSEL;
+ field public static final int IFF_PROMISC;
+ field public static final int IFF_RUNNING;
+ field public static final int IFF_SLAVE;
+ field public static final int IFF_UP;
+ field public static final int IPPROTO_ICMP;
+ field public static final int IPPROTO_ICMPV6;
+ field public static final int IPPROTO_IP;
+ field public static final int IPPROTO_IPV6;
+ field public static final int IPPROTO_RAW;
+ field public static final int IPPROTO_TCP;
+ field public static final int IPPROTO_UDP;
+ field public static final int IPV6_CHECKSUM;
+ field public static final int IPV6_MULTICAST_HOPS;
+ field public static final int IPV6_MULTICAST_IF;
+ field public static final int IPV6_MULTICAST_LOOP;
+ field public static final int IPV6_RECVDSTOPTS;
+ field public static final int IPV6_RECVHOPLIMIT;
+ field public static final int IPV6_RECVHOPOPTS;
+ field public static final int IPV6_RECVPKTINFO;
+ field public static final int IPV6_RECVRTHDR;
+ field public static final int IPV6_RECVTCLASS;
+ field public static final int IPV6_TCLASS;
+ field public static final int IPV6_UNICAST_HOPS;
+ field public static final int IPV6_V6ONLY;
+ field public static final int IP_MULTICAST_IF;
+ field public static final int IP_MULTICAST_LOOP;
+ field public static final int IP_MULTICAST_TTL;
+ field public static final int IP_TOS;
+ field public static final int IP_TTL;
+ field public static final int MAP_FIXED;
+ field public static final int MAP_PRIVATE;
+ field public static final int MAP_SHARED;
+ field public static final int MCAST_BLOCK_SOURCE;
+ field public static final int MCAST_JOIN_GROUP;
+ field public static final int MCAST_JOIN_SOURCE_GROUP;
+ field public static final int MCAST_LEAVE_GROUP;
+ field public static final int MCAST_LEAVE_SOURCE_GROUP;
+ field public static final int MCAST_UNBLOCK_SOURCE;
+ field public static final int MCL_CURRENT;
+ field public static final int MCL_FUTURE;
+ field public static final int MSG_CTRUNC;
+ field public static final int MSG_DONTROUTE;
+ field public static final int MSG_EOR;
+ field public static final int MSG_OOB;
+ field public static final int MSG_PEEK;
+ field public static final int MSG_TRUNC;
+ field public static final int MSG_WAITALL;
+ field public static final int MS_ASYNC;
+ field public static final int MS_INVALIDATE;
+ field public static final int MS_SYNC;
+ field public static final int NI_DGRAM;
+ field public static final int NI_NAMEREQD;
+ field public static final int NI_NOFQDN;
+ field public static final int NI_NUMERICHOST;
+ field public static final int NI_NUMERICSERV;
+ field public static final int O_ACCMODE;
+ field public static final int O_APPEND;
+ field public static final int O_CREAT;
+ field public static final int O_EXCL;
+ field public static final int O_NOCTTY;
+ field public static final int O_NOFOLLOW;
+ field public static final int O_NONBLOCK;
+ field public static final int O_RDONLY;
+ field public static final int O_RDWR;
+ field public static final int O_SYNC;
+ field public static final int O_TRUNC;
+ field public static final int O_WRONLY;
+ field public static final int POLLERR;
+ field public static final int POLLHUP;
+ field public static final int POLLIN;
+ field public static final int POLLNVAL;
+ field public static final int POLLOUT;
+ field public static final int POLLPRI;
+ field public static final int POLLRDBAND;
+ field public static final int POLLRDNORM;
+ field public static final int POLLWRBAND;
+ field public static final int POLLWRNORM;
+ field public static final int PROT_EXEC;
+ field public static final int PROT_NONE;
+ field public static final int PROT_READ;
+ field public static final int PROT_WRITE;
+ field public static final int PR_SET_NO_NEW_PRIVS;
+ field public static final int RT_SCOPE_HOST;
+ field public static final int RT_SCOPE_LINK;
+ field public static final int RT_SCOPE_NOWHERE;
+ field public static final int RT_SCOPE_SITE;
+ field public static final int RT_SCOPE_UNIVERSE;
+ field public static final int R_OK;
+ field public static final int SEEK_CUR;
+ field public static final int SEEK_END;
+ field public static final int SEEK_SET;
+ field public static final int SHUT_RD;
+ field public static final int SHUT_RDWR;
+ field public static final int SHUT_WR;
+ field public static final int SIGABRT;
+ field public static final int SIGALRM;
+ field public static final int SIGBUS;
+ field public static final int SIGCHLD;
+ field public static final int SIGCONT;
+ field public static final int SIGFPE;
+ field public static final int SIGHUP;
+ field public static final int SIGILL;
+ field public static final int SIGINT;
+ field public static final int SIGIO;
+ field public static final int SIGKILL;
+ field public static final int SIGPIPE;
+ field public static final int SIGPROF;
+ field public static final int SIGPWR;
+ field public static final int SIGQUIT;
+ field public static final int SIGRTMAX;
+ field public static final int SIGRTMIN;
+ field public static final int SIGSEGV;
+ field public static final int SIGSTKFLT;
+ field public static final int SIGSTOP;
+ field public static final int SIGSYS;
+ field public static final int SIGTERM;
+ field public static final int SIGTRAP;
+ field public static final int SIGTSTP;
+ field public static final int SIGTTIN;
+ field public static final int SIGTTOU;
+ field public static final int SIGURG;
+ field public static final int SIGUSR1;
+ field public static final int SIGUSR2;
+ field public static final int SIGVTALRM;
+ field public static final int SIGWINCH;
+ field public static final int SIGXCPU;
+ field public static final int SIGXFSZ;
+ field public static final int SIOCGIFADDR;
+ field public static final int SIOCGIFBRDADDR;
+ field public static final int SIOCGIFDSTADDR;
+ field public static final int SIOCGIFNETMASK;
+ field public static final int SOCK_DGRAM;
+ field public static final int SOCK_RAW;
+ field public static final int SOCK_SEQPACKET;
+ field public static final int SOCK_STREAM;
+ field public static final int SOL_SOCKET;
+ field public static final int SO_BINDTODEVICE;
+ field public static final int SO_BROADCAST;
+ field public static final int SO_DEBUG;
+ field public static final int SO_DONTROUTE;
+ field public static final int SO_ERROR;
+ field public static final int SO_KEEPALIVE;
+ field public static final int SO_LINGER;
+ field public static final int SO_OOBINLINE;
+ field public static final int SO_PASSCRED;
+ field public static final int SO_PEERCRED;
+ field public static final int SO_RCVBUF;
+ field public static final int SO_RCVLOWAT;
+ field public static final int SO_RCVTIMEO;
+ field public static final int SO_REUSEADDR;
+ field public static final int SO_SNDBUF;
+ field public static final int SO_SNDLOWAT;
+ field public static final int SO_SNDTIMEO;
+ field public static final int SO_TYPE;
+ field public static final int STDERR_FILENO;
+ field public static final int STDIN_FILENO;
+ field public static final int STDOUT_FILENO;
+ field public static final int S_IFBLK;
+ field public static final int S_IFCHR;
+ field public static final int S_IFDIR;
+ field public static final int S_IFIFO;
+ field public static final int S_IFLNK;
+ field public static final int S_IFMT;
+ field public static final int S_IFREG;
+ field public static final int S_IFSOCK;
+ field public static final int S_IRGRP;
+ field public static final int S_IROTH;
+ field public static final int S_IRUSR;
+ field public static final int S_IRWXG;
+ field public static final int S_IRWXO;
+ field public static final int S_IRWXU;
+ field public static final int S_ISGID;
+ field public static final int S_ISUID;
+ field public static final int S_ISVTX;
+ field public static final int S_IWGRP;
+ field public static final int S_IWOTH;
+ field public static final int S_IWUSR;
+ field public static final int S_IXGRP;
+ field public static final int S_IXOTH;
+ field public static final int S_IXUSR;
+ field public static final int TCP_NODELAY;
+ field public static final int WCONTINUED;
+ field public static final int WEXITED;
+ field public static final int WNOHANG;
+ field public static final int WNOWAIT;
+ field public static final int WSTOPPED;
+ field public static final int WUNTRACED;
+ field public static final int W_OK;
+ field public static final int X_OK;
+ field public static final int _SC_2_CHAR_TERM;
+ field public static final int _SC_2_C_BIND;
+ field public static final int _SC_2_C_DEV;
+ field public static final int _SC_2_C_VERSION;
+ field public static final int _SC_2_FORT_DEV;
+ field public static final int _SC_2_FORT_RUN;
+ field public static final int _SC_2_LOCALEDEF;
+ field public static final int _SC_2_SW_DEV;
+ field public static final int _SC_2_UPE;
+ field public static final int _SC_2_VERSION;
+ field public static final int _SC_AIO_LISTIO_MAX;
+ field public static final int _SC_AIO_MAX;
+ field public static final int _SC_AIO_PRIO_DELTA_MAX;
+ field public static final int _SC_ARG_MAX;
+ field public static final int _SC_ASYNCHRONOUS_IO;
+ field public static final int _SC_ATEXIT_MAX;
+ field public static final int _SC_AVPHYS_PAGES;
+ field public static final int _SC_BC_BASE_MAX;
+ field public static final int _SC_BC_DIM_MAX;
+ field public static final int _SC_BC_SCALE_MAX;
+ field public static final int _SC_BC_STRING_MAX;
+ field public static final int _SC_CHILD_MAX;
+ field public static final int _SC_CLK_TCK;
+ field public static final int _SC_COLL_WEIGHTS_MAX;
+ field public static final int _SC_DELAYTIMER_MAX;
+ field public static final int _SC_EXPR_NEST_MAX;
+ field public static final int _SC_FSYNC;
+ field public static final int _SC_GETGR_R_SIZE_MAX;
+ field public static final int _SC_GETPW_R_SIZE_MAX;
+ field public static final int _SC_IOV_MAX;
+ field public static final int _SC_JOB_CONTROL;
+ field public static final int _SC_LINE_MAX;
+ field public static final int _SC_LOGIN_NAME_MAX;
+ field public static final int _SC_MAPPED_FILES;
+ field public static final int _SC_MEMLOCK;
+ field public static final int _SC_MEMLOCK_RANGE;
+ field public static final int _SC_MEMORY_PROTECTION;
+ field public static final int _SC_MESSAGE_PASSING;
+ field public static final int _SC_MQ_OPEN_MAX;
+ field public static final int _SC_MQ_PRIO_MAX;
+ field public static final int _SC_NGROUPS_MAX;
+ field public static final int _SC_NPROCESSORS_CONF;
+ field public static final int _SC_NPROCESSORS_ONLN;
+ field public static final int _SC_OPEN_MAX;
+ field public static final int _SC_PAGESIZE;
+ field public static final int _SC_PAGE_SIZE;
+ field public static final int _SC_PASS_MAX;
+ field public static final int _SC_PHYS_PAGES;
+ field public static final int _SC_PRIORITIZED_IO;
+ field public static final int _SC_PRIORITY_SCHEDULING;
+ field public static final int _SC_REALTIME_SIGNALS;
+ field public static final int _SC_RE_DUP_MAX;
+ field public static final int _SC_RTSIG_MAX;
+ field public static final int _SC_SAVED_IDS;
+ field public static final int _SC_SEMAPHORES;
+ field public static final int _SC_SEM_NSEMS_MAX;
+ field public static final int _SC_SEM_VALUE_MAX;
+ field public static final int _SC_SHARED_MEMORY_OBJECTS;
+ field public static final int _SC_SIGQUEUE_MAX;
+ field public static final int _SC_STREAM_MAX;
+ field public static final int _SC_SYNCHRONIZED_IO;
+ field public static final int _SC_THREADS;
+ field public static final int _SC_THREAD_ATTR_STACKADDR;
+ field public static final int _SC_THREAD_ATTR_STACKSIZE;
+ field public static final int _SC_THREAD_DESTRUCTOR_ITERATIONS;
+ field public static final int _SC_THREAD_KEYS_MAX;
+ field public static final int _SC_THREAD_PRIORITY_SCHEDULING;
+ field public static final int _SC_THREAD_PRIO_INHERIT;
+ field public static final int _SC_THREAD_PRIO_PROTECT;
+ field public static final int _SC_THREAD_SAFE_FUNCTIONS;
+ field public static final int _SC_THREAD_STACK_MIN;
+ field public static final int _SC_THREAD_THREADS_MAX;
+ field public static final int _SC_TIMERS;
+ field public static final int _SC_TIMER_MAX;
+ field public static final int _SC_TTY_NAME_MAX;
+ field public static final int _SC_TZNAME_MAX;
+ field public static final int _SC_VERSION;
+ field public static final int _SC_XBS5_ILP32_OFF32;
+ field public static final int _SC_XBS5_ILP32_OFFBIG;
+ field public static final int _SC_XBS5_LP64_OFF64;
+ field public static final int _SC_XBS5_LPBIG_OFFBIG;
+ field public static final int _SC_XOPEN_CRYPT;
+ field public static final int _SC_XOPEN_ENH_I18N;
+ field public static final int _SC_XOPEN_LEGACY;
+ field public static final int _SC_XOPEN_REALTIME;
+ field public static final int _SC_XOPEN_REALTIME_THREADS;
+ field public static final int _SC_XOPEN_SHM;
+ field public static final int _SC_XOPEN_UNIX;
+ field public static final int _SC_XOPEN_VERSION;
+ field public static final int _SC_XOPEN_XCU_VERSION;
+ }
+
+ public final class StructPollfd {
+ ctor public StructPollfd();
+ field public short events;
+ field public java.io.FileDescriptor fd;
+ field public short revents;
+ field public java.lang.Object userData;
+ }
+
+ public final class StructStat {
+ ctor public StructStat(long, long, int, long, int, int, long, long, long, long, long, long, long);
+ field public final long st_atime;
+ field public final long st_blksize;
+ field public final long st_blocks;
+ field public final long st_ctime;
+ field public final long st_dev;
+ field public final int st_gid;
+ field public final long st_ino;
+ field public final int st_mode;
+ field public final long st_mtime;
+ field public final long st_nlink;
+ field public final long st_rdev;
+ field public final long st_size;
+ field public final int st_uid;
+ }
+
+ public final class StructStatVfs {
+ ctor public StructStatVfs(long, long, long, long, long, long, long, long, long, long, long);
+ field public final long f_bavail;
+ field public final long f_bfree;
+ field public final long f_blocks;
+ field public final long f_bsize;
+ field public final long f_favail;
+ field public final long f_ffree;
+ field public final long f_files;
+ field public final long f_flag;
+ field public final long f_frsize;
+ field public final long f_fsid;
+ field public final long f_namemax;
+ }
+
+ public final class StructUtsname {
+ ctor public StructUtsname(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+ field public final java.lang.String machine;
+ field public final java.lang.String nodename;
+ field public final java.lang.String release;
+ field public final java.lang.String sysname;
+ field public final java.lang.String version;
+ }
+
+}
+
package android.telephony {
public final class CellIdentityCdma implements android.os.Parcelable {
@@ -28875,6 +29513,46 @@
method public void previousMonth();
}
+ public final class MutableBoolean {
+ ctor public MutableBoolean(boolean);
+ field public boolean value;
+ }
+
+ public final class MutableByte {
+ ctor public MutableByte(byte);
+ field public byte value;
+ }
+
+ public final class MutableChar {
+ ctor public MutableChar(char);
+ field public char value;
+ }
+
+ public final class MutableDouble {
+ ctor public MutableDouble(double);
+ field public double value;
+ }
+
+ public final class MutableFloat {
+ ctor public MutableFloat(float);
+ field public float value;
+ }
+
+ public final class MutableInt {
+ ctor public MutableInt(int);
+ field public int value;
+ }
+
+ public final class MutableLong {
+ ctor public MutableLong(long);
+ field public long value;
+ }
+
+ public final class MutableShort {
+ ctor public MutableShort(short);
+ field public short value;
+ }
+
public class NoSuchPropertyException extends java.lang.RuntimeException {
ctor public NoSuchPropertyException(java.lang.String);
}
@@ -32548,6 +33226,34 @@
field public static final android.os.Parcelable.Creator CREATOR;
}
+ public final class CursorAnchorInfo implements android.os.Parcelable {
+ ctor public CursorAnchorInfo(android.os.Parcel);
+ method public int describeContents();
+ method public int getCandidatesEnd();
+ method public int getCandidatesStart();
+ method public android.graphics.RectF getCharacterRect(int);
+ method public float getInsertionMarkerBaseline();
+ method public float getInsertionMarkerBottom();
+ method public float getInsertionMarkerHorizontal();
+ method public float getInsertionMarkerTop();
+ method public android.graphics.Matrix getMatrix();
+ method public int getSelectionEnd();
+ method public int getSelectionStart();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
+ public static final class CursorAnchorInfo.CursorAnchorInfoBuilder {
+ ctor public CursorAnchorInfo.CursorAnchorInfoBuilder();
+ method public android.view.inputmethod.CursorAnchorInfo.CursorAnchorInfoBuilder addCharacterRect(int, float, float, float, float);
+ method public android.view.inputmethod.CursorAnchorInfo build();
+ method public void reset();
+ method public android.view.inputmethod.CursorAnchorInfo.CursorAnchorInfoBuilder setCandidateRange(int, int);
+ method public android.view.inputmethod.CursorAnchorInfo.CursorAnchorInfoBuilder setInsertionMarkerLocation(float, float, float, float);
+ method public android.view.inputmethod.CursorAnchorInfo.CursorAnchorInfoBuilder setMatrix(android.graphics.Matrix);
+ method public android.view.inputmethod.CursorAnchorInfo.CursorAnchorInfoBuilder setSelectionRange(int, int);
+ }
+
public class EditorInfo implements android.text.InputType android.os.Parcelable {
ctor public EditorInfo();
method public int describeContents();
@@ -32756,6 +33462,7 @@
method public void toggleSoftInput(int, int);
method public void toggleSoftInputFromWindow(android.os.IBinder, int, int);
method public void updateCursor(android.view.View, int, int, int, int);
+ method public void updateCursorAnchorInfo(android.view.View, android.view.inputmethod.CursorAnchorInfo);
method public void updateExtractedText(android.view.View, int, android.view.inputmethod.ExtractedText);
method public void updateSelection(android.view.View, int, int, int, int);
method public void viewClicked(android.view.View);
@@ -32778,6 +33485,7 @@
method public abstract void finishInput();
method public abstract void toggleSoftInput(int, int);
method public abstract void updateCursor(android.graphics.Rect);
+ method public abstract void updateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo);
method public abstract void updateExtractedText(int, android.view.inputmethod.ExtractedText);
method public abstract void updateSelection(int, int, int, int, int, int);
method public abstract void viewClicked(boolean);
@@ -33027,7 +33735,6 @@
method public abstract long getResources();
method public abstract void grant(long);
field public static final long RESOURCE_AUDIO_CAPTURE = 4L; // 0x4L
- field public static final long RESOURCE_GEOLOCATION = 1L; // 0x1L
field public static final long RESOURCE_VIDEO_CAPTURE = 2L; // 0x2L
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 36f9f4b..ef6fcb7 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4807,6 +4807,7 @@
public void setRecentsActivityValues(ActivityManager.RecentsActivityValues values) {
ActivityManager.RecentsActivityValues activityValues =
new ActivityManager.RecentsActivityValues(values);
+ // Scale the icon down to something reasonable
if (values.icon != null) {
final int size = ActivityManager.getLauncherLargeIconSizeInner(this);
activityValues.icon = Bitmap.createScaledBitmap(values.icon, size, size, true);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 5d809d8..044727d 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -20,7 +20,6 @@
import android.os.IBinder;
import com.android.internal.app.IUsageStats;
import com.android.internal.app.ProcessStats;
-import com.android.internal.os.PkgUsageStats;
import com.android.internal.os.TransferPipe;
import com.android.internal.util.FastPrintWriter;
@@ -2130,14 +2129,15 @@
return new HashMap<String, Integer>();
}
- PkgUsageStats[] allPkgUsageStats = usageStatsService.getAllPkgUsageStats();
+ UsageStats.PackageStats[] allPkgUsageStats = usageStatsService.getAllPkgUsageStats(
+ ActivityThread.currentPackageName());
if (allPkgUsageStats == null) {
return new HashMap<String, Integer>();
}
Map<String, Integer> launchCounts = new HashMap<String, Integer>();
- for (PkgUsageStats pkgUsageStats : allPkgUsageStats) {
- launchCounts.put(pkgUsageStats.packageName, pkgUsageStats.launchCount);
+ for (UsageStats.PackageStats pkgUsageStats : allPkgUsageStats) {
+ launchCounts.put(pkgUsageStats.getPackageName(), pkgUsageStats.getLaunchCount());
}
return launchCounts;
@@ -2251,17 +2251,17 @@
*
* @hide
*/
- public PkgUsageStats[] getAllPackageUsageStats() {
+ public UsageStats.PackageStats[] getAllPackageUsageStats() {
try {
IUsageStats usageStatsService = IUsageStats.Stub.asInterface(
ServiceManager.getService("usagestats"));
if (usageStatsService != null) {
- return usageStatsService.getAllPkgUsageStats();
+ return usageStatsService.getAllPkgUsageStats(ActivityThread.currentPackageName());
}
} catch (RemoteException e) {
Log.w(TAG, "Could not query usage stats", e);
}
- return new PkgUsageStats[0];
+ return new UsageStats.PackageStats[0];
}
/**
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index b616c1e..d813dab 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -16,6 +16,7 @@
package android.app;
+import android.Manifest;
import android.os.Binder;
import android.os.IBinder;
import android.util.ArrayMap;
@@ -184,8 +185,10 @@
public static final int OP_MONITOR_LOCATION = 41;
/** @hide Continually monitoring location data with a relatively high power request. */
public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42;
+ /** @hide Retrieve current usage stats via {@link UsageStatsManager}. */
+ public static final int OP_GET_USAGE_STATS = 43;
/** @hide */
- public static final int _NUM_OP = 43;
+ public static final int _NUM_OP = 44;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION =
@@ -252,6 +255,7 @@
OP_WAKE_LOCK,
OP_COARSE_LOCATION,
OP_COARSE_LOCATION,
+ OP_GET_USAGE_STATS,
};
/**
@@ -302,6 +306,7 @@
null,
OPSTR_MONITOR_LOCATION,
OPSTR_MONITOR_HIGH_POWER_LOCATION,
+ null,
};
/**
@@ -352,6 +357,7 @@
"WAKE_LOCK",
"MONITOR_LOCATION",
"MONITOR_HIGH_POWER_LOCATION",
+ "GET_USAGE_STATS"
};
/**
@@ -402,6 +408,7 @@
android.Manifest.permission.WAKE_LOCK,
null, // no permission for generic location monitoring
null, // no permission for high power location monitoring
+ android.Manifest.permission.PACKAGE_USAGE_STATS,
};
/**
@@ -451,6 +458,7 @@
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED,
+ AppOpsManager.MODE_IGNORED, // OP_GET_USAGE_STATS
};
/**
@@ -504,6 +512,7 @@
false,
false,
false,
+ false,
};
private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 5ed5030..801182d 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -678,6 +678,11 @@
return new NetworkScoreManager(ctx);
}
});
+
+ registerService(USAGE_STATS_SERVICE, new ServiceFetcher() {
+ public Object createService(ContextImpl ctx) {
+ return new UsageStatsManager(ctx.getOuterContext());
+ }});
}
static ContextImpl getImpl(Context context) {
diff --git a/core/java/android/app/UsageStats.aidl b/core/java/android/app/UsageStats.aidl
new file mode 100644
index 0000000..7dee70a
--- /dev/null
+++ b/core/java/android/app/UsageStats.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+parcelable UsageStats;
+parcelable UsageStats.PackageStats;
diff --git a/core/java/android/app/UsageStats.java b/core/java/android/app/UsageStats.java
new file mode 100644
index 0000000..0aeba59
--- /dev/null
+++ b/core/java/android/app/UsageStats.java
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.res.Configuration;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.SystemClock;
+import android.util.ArrayMap;
+
+import java.util.Map;
+
+/**
+ * Snapshot of current usage stats data.
+ * @hide
+ */
+public class UsageStats implements Parcelable {
+ /** @hide */
+ public final ArrayMap<String, PackageStats> mPackages = new ArrayMap<String, PackageStats>();
+ /** @hide */
+ public final ArrayMap<Configuration, ConfigurationStats> mConfigurations
+ = new ArrayMap<Configuration, ConfigurationStats>();
+
+ public static class PackageStats implements Parcelable {
+ private final String mPackageName;
+ private int mLaunchCount;
+ private long mUsageTime;
+ private long mResumedTime;
+
+ /** @hide */
+ public final ArrayMap<String, Long> componentResumeTimes;
+
+ public static final Parcelable.Creator<PackageStats> CREATOR
+ = new Parcelable.Creator<PackageStats>() {
+ public PackageStats createFromParcel(Parcel in) {
+ return new PackageStats(in);
+ }
+
+ public PackageStats[] newArray(int size) {
+ return new PackageStats[size];
+ }
+ };
+
+ public String toString() {
+ return "PackageStats{"
+ + Integer.toHexString(System.identityHashCode(this))
+ + " " + mPackageName + "}";
+ }
+
+ /** @hide */
+ public PackageStats(String pkgName) {
+ mPackageName = pkgName;
+ componentResumeTimes = new ArrayMap<String, Long>();
+ }
+
+ /** @hide */
+ public PackageStats(String pkgName, int count, long time, Map<String, Long> lastResumeTimes) {
+ mPackageName = pkgName;
+ mLaunchCount = count;
+ mUsageTime = time;
+ componentResumeTimes = new ArrayMap<String, Long>();
+ componentResumeTimes.putAll(lastResumeTimes);
+ }
+
+ /** @hide */
+ public PackageStats(Parcel source) {
+ mPackageName = source.readString();
+ mLaunchCount = source.readInt();
+ mUsageTime = source.readLong();
+ final int N = source.readInt();
+ componentResumeTimes = new ArrayMap<String, Long>(N);
+ for (int i = 0; i < N; i++) {
+ String component = source.readString();
+ long lastResumeTime = source.readLong();
+ componentResumeTimes.put(component, lastResumeTime);
+ }
+ }
+
+ /** @hide */
+ public PackageStats(PackageStats pStats) {
+ mPackageName = pStats.mPackageName;
+ mLaunchCount = pStats.mLaunchCount;
+ mUsageTime = pStats.mUsageTime;
+ componentResumeTimes = new ArrayMap<String, Long>(pStats.componentResumeTimes);
+ }
+
+ /** @hide */
+ public void resume(boolean launched) {
+ if (launched) {
+ mLaunchCount++;
+ }
+ mResumedTime = SystemClock.elapsedRealtime();
+ }
+
+ /** @hide */
+ public void pause() {
+ if (mResumedTime > 0) {
+ mUsageTime += SystemClock.elapsedRealtime() - mResumedTime;
+ }
+ mResumedTime = 0;
+ }
+
+ public final String getPackageName() {
+ return mPackageName;
+ }
+
+ public final long getUsageTime(long elapsedRealtime) {
+ return mUsageTime + (mResumedTime > 0 ? (elapsedRealtime- mResumedTime) : 0);
+ }
+
+ public final int getLaunchCount() {
+ return mLaunchCount;
+ }
+
+ /** @hide */
+ public boolean clearUsageTimes() {
+ mLaunchCount = 0;
+ mUsageTime = 0;
+ return mResumedTime <= 0 && componentResumeTimes.isEmpty();
+ }
+
+ public final int describeContents() {
+ return 0;
+ }
+
+ public final void writeToParcel(Parcel dest, int parcelableFlags) {
+ writeToParcel(dest, parcelableFlags, 0);
+ }
+
+ final void writeToParcel(Parcel dest, int parcelableFlags, long elapsedRealtime) {
+ dest.writeString(mPackageName);
+ dest.writeInt(mLaunchCount);
+ dest.writeLong(elapsedRealtime > 0 ? getUsageTime(elapsedRealtime) : mUsageTime);
+ dest.writeInt(componentResumeTimes.size());
+ for (Map.Entry<String, Long> ent : componentResumeTimes.entrySet()) {
+ dest.writeString(ent.getKey());
+ dest.writeLong(ent.getValue());
+ }
+ }
+
+ /** @hide */
+ public void writeExtendedToParcel(Parcel dest, int parcelableFlags) {
+ }
+ }
+
+ public static class ConfigurationStats implements Parcelable {
+ private final Configuration mConfiguration;
+ private long mLastUsedTime;
+ private int mUsageCount;
+ private long mUsageTime;
+ private long mStartedTime;
+
+ public static final Parcelable.Creator<ConfigurationStats> CREATOR
+ = new Parcelable.Creator<ConfigurationStats>() {
+ public ConfigurationStats createFromParcel(Parcel in) {
+ return new ConfigurationStats(in);
+ }
+
+ public ConfigurationStats[] newArray(int size) {
+ return new ConfigurationStats[size];
+ }
+ };
+
+ public String toString() {
+ return "ConfigurationStats{"
+ + Integer.toHexString(System.identityHashCode(this))
+ + " " + mConfiguration + "}";
+ }
+
+ /** @hide */
+ public ConfigurationStats(Configuration config) {
+ mConfiguration = config;
+ }
+
+ /** @hide */
+ public ConfigurationStats(Parcel source) {
+ mConfiguration = Configuration.CREATOR.createFromParcel(source);
+ mLastUsedTime = source.readLong();
+ mUsageCount = source.readInt();
+ mUsageTime = source.readLong();
+ }
+
+ /** @hide */
+ public ConfigurationStats(ConfigurationStats pStats) {
+ mConfiguration = pStats.mConfiguration;
+ mLastUsedTime = pStats.mLastUsedTime;
+ mUsageCount = pStats.mUsageCount;
+ mUsageTime = pStats.mUsageTime;
+ }
+
+ public final Configuration getConfiguration() {
+ return mConfiguration;
+ }
+
+ public final long getLastUsedTime() {
+ return mLastUsedTime;
+ }
+
+ public final long getUsageTime(long elapsedRealtime) {
+ return mUsageTime + (mStartedTime > 0 ? (elapsedRealtime- mStartedTime) : 0);
+ }
+
+ public final int getUsageCount() {
+ return mUsageCount;
+ }
+
+ /** @hide */
+ public void start() {
+ mLastUsedTime = System.currentTimeMillis();
+ mUsageCount++;
+ mStartedTime = SystemClock.elapsedRealtime();
+ }
+
+ /** @hide */
+ public void stop() {
+ if (mStartedTime > 0) {
+ mUsageTime += SystemClock.elapsedRealtime() - mStartedTime;
+ }
+ mStartedTime = 0;
+ }
+
+ /** @hide */
+ public boolean clearUsageTimes() {
+ mUsageCount = 0;
+ mUsageTime = 0;
+ return mLastUsedTime == 0 && mStartedTime <= 0;
+ }
+
+ public final int describeContents() {
+ return 0;
+ }
+
+ public final void writeToParcel(Parcel dest, int parcelableFlags) {
+ writeToParcel(dest, parcelableFlags, 0);
+ }
+
+ final void writeToParcel(Parcel dest, int parcelableFlags, long elapsedRealtime) {
+ mConfiguration.writeToParcel(dest, parcelableFlags);
+ dest.writeLong(mLastUsedTime);
+ dest.writeInt(mUsageCount);
+ dest.writeLong(elapsedRealtime > 0 ? getUsageTime(elapsedRealtime) : mUsageTime);
+ }
+
+ /** @hide */
+ public void writeExtendedToParcel(Parcel dest, int parcelableFlags) {
+ }
+ }
+
+ /** @hide */
+ public UsageStats() {
+ }
+
+ /** @hide */
+ public UsageStats(Parcel source, boolean extended) {
+ int N = source.readInt();
+ for (int i=0; i<N; i++) {
+ PackageStats pkg = extended ? onNewPackageStats(source) : new PackageStats(source);
+ mPackages.put(pkg.getPackageName(), pkg);
+ }
+ N = source.readInt();
+ for (int i=0; i<N; i++) {
+ ConfigurationStats config = extended ? onNewConfigurationStats(source)
+ : new ConfigurationStats(source);
+ mConfigurations.put(config.getConfiguration(), config);
+ }
+ }
+
+ public int getPackageStatsCount() {
+ return mPackages.size();
+ }
+
+ public PackageStats getPackageStatsAt(int index) {
+ return mPackages.valueAt(index);
+ }
+
+ public PackageStats getPackageStats(String pkgName) {
+ return mPackages.get(pkgName);
+ }
+
+ /** @hide */
+ public PackageStats getOrCreatePackageStats(String pkgName) {
+ PackageStats ps = mPackages.get(pkgName);
+ if (ps == null) {
+ ps = onNewPackageStats(pkgName);
+ mPackages.put(pkgName, ps);
+ }
+ return ps;
+ }
+
+ public int getConfigurationStatsCount() {
+ return mConfigurations.size();
+ }
+
+ public ConfigurationStats getConfigurationStatsAt(int index) {
+ return mConfigurations.valueAt(index);
+ }
+
+ public ConfigurationStats getConfigurationStats(Configuration config) {
+ return mConfigurations.get(config);
+ }
+
+ /** @hide */
+ public ConfigurationStats getOrCreateConfigurationStats(Configuration config) {
+ ConfigurationStats cs = mConfigurations.get(config);
+ if (cs == null) {
+ cs = onNewConfigurationStats(config);
+ mConfigurations.put(config, cs);
+ }
+ return cs;
+ }
+
+ /** @hide */
+ public void clearUsageTimes() {
+ for (int i=mPackages.size()-1; i>=0; i--) {
+ if (mPackages.valueAt(i).clearUsageTimes()) {
+ mPackages.removeAt(i);
+ }
+ }
+ for (int i=mConfigurations.size()-1; i>=0; i--) {
+ if (mConfigurations.valueAt(i).clearUsageTimes()) {
+ mConfigurations.removeAt(i);
+ }
+ }
+ }
+
+ /** @hide */
+ public PackageStats onNewPackageStats(String pkgName) {
+ return new PackageStats(pkgName);
+ }
+
+ /** @hide */
+ public PackageStats onNewPackageStats(Parcel source) {
+ return new PackageStats(source);
+ }
+
+ /** @hide */
+ public ConfigurationStats onNewConfigurationStats(Configuration config) {
+ return new ConfigurationStats(config);
+ }
+
+ /** @hide */
+ public ConfigurationStats onNewConfigurationStats(Parcel source) {
+ return new ConfigurationStats(source);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int parcelableFlags) {
+ writeToParcelInner(dest, parcelableFlags, false);
+ }
+
+ /** @hide */
+ public void writeExtendedToParcel(Parcel dest, int parcelableFlags) {
+ writeToParcelInner(dest, parcelableFlags, true);
+ }
+
+ private void writeToParcelInner(Parcel dest, int parcelableFlags, boolean extended) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+
+ int N = mPackages.size();
+ dest.writeInt(N);
+ for (int i=0; i<N; i++) {
+ PackageStats ps = mPackages.valueAt(i);
+ ps.writeToParcel(dest, parcelableFlags, elapsedRealtime);
+ if (extended) {
+ ps.writeExtendedToParcel(dest, parcelableFlags);
+ }
+ }
+ N = mConfigurations.size();
+ dest.writeInt(N);
+ for (int i=0; i<N; i++) {
+ ConfigurationStats cs = mConfigurations.valueAt(i);
+ cs.writeToParcel(dest, parcelableFlags, elapsedRealtime);
+ if (extended) {
+ cs.writeExtendedToParcel(dest, parcelableFlags);
+ }
+ }
+ }
+
+ public static final Parcelable.Creator<UsageStats> CREATOR
+ = new Parcelable.Creator<UsageStats>() {
+ public UsageStats createFromParcel(Parcel in) {
+ return new UsageStats(in, false);
+ }
+
+ public UsageStats[] newArray(int size) {
+ return new UsageStats[size];
+ }
+ };
+}
diff --git a/core/java/android/app/UsageStatsManager.java b/core/java/android/app/UsageStatsManager.java
new file mode 100644
index 0000000..fbf9c3b
--- /dev/null
+++ b/core/java/android/app/UsageStatsManager.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.Context;
+import android.os.ParcelableParcel;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import com.android.internal.app.IUsageStats;
+
+/**
+ * Access to usage stats data.
+ * @hide
+ */
+public class UsageStatsManager {
+ final Context mContext;
+ final IUsageStats mService;
+
+ /** @hide */
+ public UsageStatsManager(Context context) {
+ mContext = context;
+ mService = IUsageStats.Stub.asInterface(ServiceManager.getService(
+ Context.USAGE_STATS_SERVICE));
+ }
+
+ public UsageStats getCurrentStats() {
+ try {
+ ParcelableParcel in = mService.getCurrentStats(mContext.getOpPackageName());
+ if (in != null) {
+ return new UsageStats(in.getParcel(), false);
+ }
+ } catch (RemoteException e) {
+ // About to die.
+ }
+ return new UsageStats();
+ }
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 61ff60a..58049fd 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -16,8 +16,6 @@
package android.app.admin;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ComponentName;
@@ -39,6 +37,8 @@
import com.android.org.conscrypt.TrustedCertificateStore;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
@@ -359,8 +359,8 @@
}
/**
- * Retrieve the current minimum password quality for all admins
- * or a particular one.
+ * Retrieve the current minimum password quality for all admins of this user
+ * and its profiles or a particular one.
* @param admin The name of the admin component to check, or null to aggregate
* all admins.
*/
@@ -412,8 +412,8 @@
}
/**
- * Retrieve the current minimum password length for all admins
- * or a particular one.
+ * Retrieve the current minimum password length for all admins of this
+ * user and its profiles or a particular one.
* @param admin The name of the admin component to check, or null to aggregate
* all admins.
*/
@@ -467,8 +467,9 @@
/**
* Retrieve the current number of upper case letters required in the
- * password for all admins or a particular one. This is the same value as
- * set by {#link {@link #setPasswordMinimumUpperCase(ComponentName, int)}
+ * password for all admins of this user and its profiles or a particular one.
+ * This is the same value as set by
+ * {#link {@link #setPasswordMinimumUpperCase(ComponentName, int)}
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
@@ -527,8 +528,9 @@
/**
* Retrieve the current number of lower case letters required in the
- * password for all admins or a particular one. This is the same value as
- * set by {#link {@link #setPasswordMinimumLowerCase(ComponentName, int)}
+ * password for all admins of this user and its profiles or a particular one.
+ * This is the same value as set by
+ * {#link {@link #setPasswordMinimumLowerCase(ComponentName, int)}
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
@@ -644,8 +646,9 @@
/**
* Retrieve the current number of numerical digits required in the password
- * for all admins or a particular one. This is the same value as
- * set by {#link {@link #setPasswordMinimumNumeric(ComponentName, int)}
+ * for all admins of this user and its profiles or a particular one.
+ * This is the same value as set by
+ * {#link {@link #setPasswordMinimumNumeric(ComponentName, int)}
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
@@ -760,8 +763,9 @@
/**
* Retrieve the current number of non-letter characters required in the
- * password for all admins or a particular one. This is the same value as
- * set by {#link {@link #setPasswordMinimumNonLetter(ComponentName, int)}
+ * password for all admins of this user and its profiles or a particular one.
+ * This is the same value as set by
+ * {#link {@link #setPasswordMinimumNonLetter(ComponentName, int)}
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
@@ -868,9 +872,10 @@
/**
* Get the current password expiration time for the given admin or an aggregate of
- * all admins if admin is null. If the password is expired, this will return the time since
- * the password expired as a negative number. If admin is null, then a composite of all
- * expiration timeouts is returned - which will be the minimum of all timeouts.
+ * all admins of this user and its profiles if admin is null. If the password is
+ * expired, this will return the time since the password expired as a negative number.
+ * If admin is null, then a composite of all expiration timeouts is returned
+ * - which will be the minimum of all timeouts.
*
* @param admin The name of the admin component to check, or null to aggregate all admins.
* @return The password expiration time, in ms.
@@ -887,8 +892,8 @@
}
/**
- * Retrieve the current password history length for all admins
- * or a particular one.
+ * Retrieve the current password history length for all admins of this
+ * user and its profiles or a particular one.
* @param admin The name of the admin component to check, or null to aggregate
* all admins.
* @return The length of the password history
@@ -923,14 +928,13 @@
/**
* Determine whether the current password the user has set is sufficient
* to meet the policy requirements (quality, minimum length) that have been
- * requested.
+ * requested by the admins of this user and its profiles.
*
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
* this method; if it has not, a security exception will be thrown.
*
- * @return Returns true if the password meets the current requirements,
- * else false.
+ * @return Returns true if the password meets the current requirements, else false.
*/
public boolean isActivePasswordSufficient() {
if (mService != null) {
@@ -993,7 +997,7 @@
/**
* Retrieve the current maximum number of login attempts that are allowed
- * before the device wipes itself, for all admins
+ * before the device wipes itself, for all admins of this user and its profiles
* or a particular one.
* @param admin The name of the admin component to check, or null to aggregate
* all admins.
@@ -1037,6 +1041,8 @@
* {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call
* this method; if it has not, a security exception will be thrown.
*
+ * Can not be called from a managed profile.
+ *
* @param password The new password for the user.
* @param flags May be 0 or {@link #RESET_PASSWORD_REQUIRE_ENTRY}.
* @return Returns true if the password was applied, or false if it is
@@ -1077,8 +1083,8 @@
}
/**
- * Retrieve the current maximum time to unlock for all admins
- * or a particular one.
+ * Retrieve the current maximum time to unlock for all admins of this user
+ * and its profiles or a particular one.
* @param admin The name of the admin component to check, or null to aggregate
* all admins.
*/
@@ -2125,4 +2131,51 @@
return null;
}
+
+ /**
+ * Sets which components may enter lock task mode.
+ *
+ * This function can only be called by the device owner or the profile owner.
+ * @param components The list of components allowed to enter lock task mode
+ */
+ public void setLockTaskComponents(ComponentName[] components) throws SecurityException {
+ if (mService != null) {
+ try {
+ mService.setLockTaskComponents(components);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * This function returns the list of components allowed to start the lock task mode.
+ * @hide
+ */
+ public ComponentName[] getLockTaskComponents() {
+ if (mService != null) {
+ try {
+ return mService.getLockTaskComponents();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * This function lets the caller know whether the given component is allowed to start the
+ * lock task mode.
+ * @param component The component to check
+ */
+ public boolean isLockTaskPermitted(ComponentName component) {
+ if (mService != null) {
+ try {
+ return mService.isLockTaskPermitted(component);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return false;
+ }
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 0096580..03ced0f 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -129,4 +129,8 @@
void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled);
String[] getAccountTypesWithManagementDisabled();
+
+ void setLockTaskComponents(in ComponentName[] components);
+ ComponentName[] getLockTaskComponents();
+ boolean isLockTaskPermitted(in ComponentName component);
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 042ee28..a059e48 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2683,6 +2683,16 @@
public static final String NETWORK_SCORE_SERVICE = "network_score";
/**
+ * Use with {@link #getSystemService} to retrieve a {@link
+ * android.app.UsageStatsManager} for interacting with the status bar.
+ *
+ * @see #getSystemService
+ * @see android.app.UsageStatsManager
+ * @hide
+ */
+ public static final String USAGE_STATS_SERVICE = "usagestats";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 52a169b..eb2c11f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -936,13 +936,21 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device has at least one camera pointing in
- * some direction.
+ * some direction, or can support an external camera being connected to it.
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_CAMERA_ANY = "android.hardware.camera.any";
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device can support having an external camera connected to it.
+ * The external camera may not always be connected or available to applications to use.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_CAMERA_EXTERNAL = "android.hardware.camera.external";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device's camera supports flash.
*/
@SdkConstant(SdkConstantType.FEATURE)
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index 8437228..ed223d1 100644
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
@@ -36,6 +36,7 @@
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.InputMethodSession;
+import android.view.inputmethod.CursorAnchorInfo;
class IInputMethodSessionWrapper extends IInputMethodSession.Stub
implements HandlerCaller.Callback {
@@ -46,6 +47,7 @@
private static final int DO_UPDATE_EXTRACTED_TEXT = 67;
private static final int DO_UPDATE_SELECTION = 90;
private static final int DO_UPDATE_CURSOR = 95;
+ private static final int DO_UPDATE_CURSOR_ANCHOR_INFO = 99;
private static final int DO_APP_PRIVATE_COMMAND = 100;
private static final int DO_TOGGLE_SOFT_INPUT = 105;
private static final int DO_FINISH_SESSION = 110;
@@ -108,6 +110,10 @@
mInputMethodSession.updateCursor((Rect)msg.obj);
return;
}
+ case DO_UPDATE_CURSOR_ANCHOR_INFO: {
+ mInputMethodSession.updateCursorAnchorInfo((CursorAnchorInfo)msg.obj);
+ return;
+ }
case DO_APP_PRIVATE_COMMAND: {
SomeArgs args = (SomeArgs)msg.obj;
mInputMethodSession.appPrivateCommand((String)args.arg1,
@@ -181,6 +187,12 @@
}
@Override
+ public void updateCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageO(DO_UPDATE_CURSOR_ANCHOR_INFO, cursorAnchorInfo));
+ }
+
+ @Override
public void appPrivateCommand(String action, Bundle data) {
mCaller.executeOrSendMessage(
mCaller.obtainMessageOO(DO_APP_PRIVATE_COMMAND, action, data));
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index f6438b4..4bccaf1 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -51,6 +51,7 @@
import android.view.WindowManager.BadTokenException;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.CursorAnchorInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
@@ -545,6 +546,17 @@
public void toggleSoftInput(int showFlags, int hideFlags) {
InputMethodService.this.onToggleSoftInput(showFlags, hideFlags);
}
+
+ /**
+ * Call {@link InputMethodService#onUpdateCursorAnchorInfo
+ * InputMethodService.onUpdateCursorAnchorInfo()}.
+ */
+ public void updateCursorAnchorInfo(CursorAnchorInfo info) {
+ if (!isEnabled()) {
+ return;
+ }
+ InputMethodService.this.onUpdateCursorAnchorInfo(info);
+ }
}
/**
@@ -1717,6 +1729,17 @@
}
/**
+ * Called when the application has reported a new location of its text insertion point and
+ * characters in the composition string. This is only called if explicitly requested by the
+ * input method. The default implementation does nothing.
+ * @param cursorAnchorInfo The positional information of the text insertion point and the
+ * composition string.
+ */
+ public void onUpdateCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo) {
+ // Intentionally empty
+ }
+
+ /**
* Update the cursor/anthor monitor mode.
*/
public void setCursorAnchorMonitorMode(int monitorMode) {
diff --git a/core/java/android/nfc/INfcCardEmulation.aidl b/core/java/android/nfc/INfcCardEmulation.aidl
index ae9796b..521f4fd 100644
--- a/core/java/android/nfc/INfcCardEmulation.aidl
+++ b/core/java/android/nfc/INfcCardEmulation.aidl
@@ -34,4 +34,6 @@
AidGroup getAidGroupForService(int userHandle, in ComponentName service, String category);
boolean removeAidGroupForService(int userHandle, in ComponentName service, String category);
List<ApduServiceInfo> getServices(int userHandle, in String category);
+ boolean setPreferredService(in ComponentName service);
+ boolean unsetPreferredService();
}
diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/core/java/android/nfc/cardemulation/AidGroup.java
index 2820f40..b0449224 100644
--- a/core/java/android/nfc/cardemulation/AidGroup.java
+++ b/core/java/android/nfc/cardemulation/AidGroup.java
@@ -12,10 +12,15 @@
import android.util.Log;
/**
- * The AidGroup class represents a group of ISO/IEC 7816-4
- * Application Identifiers (AIDs) for a specific application
- * category, along with a description resource describing
- * the group.
+ * The AidGroup class represents a group of Application Identifiers (AIDs).
+ *
+ * <p>An instance of this object can be used with
+ * {@link CardEmulation#registerAidGroupForService(android.content.ComponentName, AidGroup)}
+ * to tell the OS which AIDs are handled by your HCE- or SE-based service.
+ *
+ * <p>The format of AIDs is defined in the ISO/IEC 7816-4 specification. This class
+ * requires the AIDs to be input as a hexadecimal string, with an even amount of
+ * hexadecimal characters, e.g. "F014811481".
*/
public final class AidGroup implements Parcelable {
/**
@@ -33,7 +38,7 @@
* Creates a new AidGroup object.
*
* @param aids The list of AIDs present in the group
- * @param category The category of this group
+ * @param category The category of this group, e.g. {@link CardEmulation#CATEGORY_PAYMENT}
*/
public AidGroup(ArrayList<String> aids, String category) {
if (aids == null || aids.size() == 0) {
@@ -42,11 +47,12 @@
if (aids.size() > MAX_NUM_AIDS) {
throw new IllegalArgumentException("Too many AIDs in AID group.");
}
- if (!isValidCategory(category)) {
- throw new IllegalArgumentException("Category specified is not valid.");
+ if (isValidCategory(category)) {
+ this.category = category;
+ } else {
+ this.category = CardEmulation.CATEGORY_OTHER;
}
this.aids = aids;
- this.category = category;
this.description = null;
}
@@ -158,7 +164,7 @@
}
}
- boolean isValidCategory(String category) {
+ static boolean isValidCategory(String category) {
return CardEmulation.CATEGORY_PAYMENT.equals(category) ||
CardEmulation.CATEGORY_OTHER.equals(category);
}
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 94f35ed..f379ee8 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -290,6 +290,20 @@
return groups;
}
+ /**
+ * Returns the category to which this service has attributed the AID that is passed in,
+ * or null if we don't know this AID.
+ */
+ public String getCategoryForAid(String aid) {
+ ArrayList<AidGroup> groups = getAidGroups();
+ for (AidGroup group : groups) {
+ if (group.aids.contains(aid)) {
+ return group.category;
+ }
+ }
+ return null;
+ }
+
public boolean hasCategory(String category) {
return (mStaticAidGroups.containsKey(category) || mDynamicAidGroups.containsKey(category));
}
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 41f039c..e24a22a 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -18,6 +18,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.app.Activity;
import android.app.ActivityThread;
import android.content.ComponentName;
import android.content.Context;
@@ -28,6 +29,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
import android.util.Log;
import java.util.HashMap;
@@ -248,6 +250,33 @@
}
/**
+ * Returns whether the user has allowed AIDs registered in the
+ * specified category to be handled by a service that is preferred
+ * by the foreground application, instead of by a pre-configured default.
+ *
+ * Foreground applications can set such preferences using the
+ * {@link #setPreferredService(Activity, ComponentName)} method.
+ *
+ * @param category The category, e.g. {@link #CATEGORY_PAYMENT}
+ * @return whether AIDs in the category can be handled by a service
+ * specified by the foreground app.
+ */
+ public boolean categoryAllowsForegroundPreference(String category) {
+ if (CATEGORY_PAYMENT.equals(category)) {
+ boolean preferForeground = false;
+ try {
+ preferForeground = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.NFC_PAYMENT_FOREGROUND) != 0;
+ } catch (SettingNotFoundException e) {
+ }
+ return preferForeground;
+ } else {
+ // Allowed for all other categories
+ return true;
+ }
+ }
+
+ /**
* Returns the service selection mode for the passed in category.
* Valid return values are:
* <p>{@link #SELECTION_MODE_PREFER_DEFAULT} the user has requested a default
@@ -269,7 +298,6 @@
return SELECTION_MODE_ALWAYS_ASK;
}
} else {
- // All other categories are in "only ask if conflict" mode
return SELECTION_MODE_ASK_IF_CONFLICT;
}
}
@@ -283,7 +311,7 @@
* that AID group will be replaced with this one.
*
* <p>Note that you can only register AIDs for a service that
- * is running under the same UID as you are. Typically
+ * is running under the same UID as the caller of this API. Typically
* this means you need to call this from the same
* package as the service itself, though UIDs can also
* be shared between packages using shared UIDs.
@@ -352,7 +380,7 @@
* method. It will *not* remove AID groups that were statically registered in
* the manifest. If a dynamically registered AID group is removed using
* this method, and a statically registered AID group for the same category
- * exists in the manifest, that AID group will become active again.
+ * exists in the manifest, the static AID group will become active again.
*
* @param service The component name of the service
* @param category The category of the AID group to be removed, e.g. {@link #CATEGORY_PAYMENT}
@@ -378,6 +406,96 @@
}
/**
+ * Allows a foreground application to specify which card emulation service
+ * should be preferred while a specific Activity is in the foreground.
+ *
+ * <p>The specified Activity must currently be in resumed state. A good
+ * paradigm is to call this method in your {@link Activity#onResume}, and to call
+ * {@link #unsetPreferredService(Activity)} in your {@link Activity#onPause}.
+ *
+ * <p>This method call will fail in two specific scenarios:
+ * <ul>
+ * <li> If the service registers one or more AIDs in the {@link #CATEGORY_PAYMENT}
+ * category, but the user has indicated that foreground apps are not allowed
+ * to override the default payment service.
+ * <li> If the service registers one or more AIDs in the {@link #CATEGORY_OTHER}
+ * category that are also handled by the default payment service, and the
+ * user has indicated that foreground apps are not allowed to override the
+ * default payment service.
+ * </ul>
+ *
+ * <p> Use {@link #categoryAllowsForegroundPreference(String)} to determine
+ * whether foreground apps can override the default payment service.
+ *
+ * <p>Note that this preference is not persisted by the OS, and hence must be
+ * called every time the Activity is resumed.
+ *
+ * @param activity The activity which prefers this service to be invoked
+ * @param service The service to be preferred while this activity is in the foreground
+ * @return whether the registration was successful
+ */
+ public boolean setPreferredService(Activity activity, ComponentName service) {
+ // Verify the activity is in the foreground before calling into NfcService
+ if (activity == null || service == null) {
+ throw new NullPointerException("activity or service or category is null");
+ }
+ if (!activity.isResumed()) {
+ throw new IllegalArgumentException("Activity must be resumed.");
+ }
+ try {
+ return sService.setPreferredService(service);
+ } catch (RemoteException e) {
+ // Try one more time
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return false;
+ }
+ try {
+ return sService.setPreferredService(service);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to reach CardEmulationService.");
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Unsets the preferred service for the specified Activity.
+ *
+ * <p>Note that the specified Activity must still be in resumed
+ * state at the time of this call. A good place to call this method
+ * is in your {@link Activity#onPause} implementation.
+ *
+ * @param activity The activity which the service was registered for
+ * @return true when successful
+ */
+ public boolean unsetPreferredService(Activity activity) {
+ if (activity == null) {
+ throw new NullPointerException("activity is null");
+ }
+ if (!activity.isResumed()) {
+ throw new IllegalArgumentException("Activity must be resumed.");
+ }
+ try {
+ return sService.unsetPreferredService();
+ } catch (RemoteException e) {
+ // Try one more time
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return false;
+ }
+ try {
+ return sService.unsetPreferredService();
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to reach CardEmulationService.");
+ return false;
+ }
+ }
+ }
+
+ /**
* @hide
*/
public boolean setDefaultServiceForCategory(ComponentName service, String category) {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index e78ce33..8b7467f 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -135,7 +135,7 @@
/**
* Bump the version on this if the checkin format changes.
*/
- private static final int BATTERY_STATS_CHECKIN_VERSION = 7;
+ private static final int BATTERY_STATS_CHECKIN_VERSION = 8;
private static final long BYTES_PER_KB = 1024;
private static final long BYTES_PER_MB = 1048576; // 1024^2
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 899a958..cd47099 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -36,6 +36,7 @@
Bitmap getUserIcon(int userHandle);
List<UserInfo> getUsers(boolean excludeDying);
List<UserInfo> getProfiles(int userHandle, boolean enabledOnly);
+ UserInfo getProfileParent(int userHandle);
UserInfo getUserInfo(int userHandle);
boolean isRestricted();
void setGuestEnabled(boolean enable);
diff --git a/core/java/android/os/ParcelableParcel.aidl b/core/java/android/os/ParcelableParcel.aidl
new file mode 100644
index 0000000..61f730c
--- /dev/null
+++ b/core/java/android/os/ParcelableParcel.aidl
@@ -0,0 +1,19 @@
+/*
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.os;
+
+parcelable ParcelableParcel;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 84639eb..312cdbe 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -234,6 +234,38 @@
*/
public static final String DISALLOW_CONFIG_APPS = "no_config_apps";
+ /**
+ * Key for user restrictions. Specifies if a user is disallowed from mounting
+ * physical external media. The default value is <code>false</code>.
+ * <p/>
+ * Type: Boolean
+ * @see #setUserRestrictions(Bundle)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
+
+ /**
+ * Key for user restrictions. Specifies if a user is disallowed from adjusting microphone
+ * volume.
+ * The default value is <code>false</code>.
+ * <p/>
+ * Type: Boolean
+ * @see #setUserRestrictions(Bundle)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_UNMUTE_MICROPHONE = "no_unmute_microphone";
+
+ /**
+ * Key for user restrictions. Specifies if a user is disallowed from adjusting the master
+ * volume.
+ * The default value is <code>false</code>.
+ * <p/>
+ * Type: Boolean
+ * @see #setUserRestrictions(Bundle)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
+
/** @hide */
public static final int PIN_VERIFICATION_FAILED_INCORRECT = -3;
/** @hide */
@@ -269,7 +301,8 @@
}
/**
- * Returns the user handle for the user that this application is running for.
+ * Returns the user handle for the user that the calling process is running on.
+ *
* @return the user handle of the user making this call.
* @hide
*/
@@ -585,7 +618,8 @@
}
/**
- * Returns a list of UserHandles for profiles associated with this user, including this user.
+ * Returns a list of UserHandles for profiles associated with the user that the calling process
+ * is running on, including the user itself.
*
* @return A non-empty list of UserHandles associated with the calling user.
*/
@@ -606,6 +640,21 @@
}
/**
+ * Returns the parent of the profile which this method is called from
+ * or null if called from a user that is not a profile.
+ *
+ * @hide
+ */
+ public UserInfo getProfileParent(int userHandle) {
+ try {
+ return mService.getProfileParent(userHandle);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Could not get profile parent", re);
+ return null;
+ }
+ }
+
+ /**
* If the target user is a managed profile of the calling user or the caller
* is itself a managed profile, then this returns a badged copy of the given
* icon to be able to distinguish it from the original icon.
@@ -632,7 +681,7 @@
private int getBadgeResIdForUser(int userHandle) {
// Return the framework-provided badge.
- List<UserInfo> userProfiles = getProfiles(UserHandle.myUserId());
+ List<UserInfo> userProfiles = getProfiles(getUserHandle());
for (UserInfo user : userProfiles) {
if (user.id == userHandle
&& user.isManagedProfile()) {
@@ -661,7 +710,7 @@
/**
* Returns information for all users on this device. Requires
* {@link android.Manifest.permission#MANAGE_USERS} permission.
- *
+ *
* @param excludeDying specify if the list should exclude users being
* removed.
* @return the list of users that were created.
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index e4f73cb..811751d 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -167,7 +167,7 @@
/**
* Callback notifying that a print job state changed.
- *
+ *
* @param printJobId The print job id.
*/
public void onPrintJobStateChanged(PrintJobId printJobId);
@@ -175,7 +175,7 @@
/**
* Creates a new instance.
- *
+ *
* @param context The current context in which to operate.
* @param service The backing system service.
* @hide
@@ -207,13 +207,17 @@
/**
* Creates an instance that can access all print jobs.
- *
+ *
* @param userId The user id for which to get all print jobs.
* @return An instance if the caller has the permission to access all print
* jobs, null otherwise.
* @hide
*/
public PrintManager getGlobalPrintManagerForUser(int userId) {
+ if (mService == null) {
+ Log.w(LOG_TAG, "Feature android.software.print not available");
+ return null;
+ }
return new PrintManager(mContext, mService, userId, APP_ID_ANY);
}
@@ -228,11 +232,15 @@
/**
* Adds a listener for observing the state of print jobs.
- *
+ *
* @param listener The listener to add.
* @hide
*/
public void addPrintJobStateChangeListener(PrintJobStateChangeListener listener) {
+ if (mService == null) {
+ Log.w(LOG_TAG, "Feature android.software.print not available");
+ return;
+ }
if (mPrintJobStateChangeListeners == null) {
mPrintJobStateChangeListeners = new ArrayMap<PrintJobStateChangeListener,
PrintJobStateChangeListenerWrapper>();
@@ -249,11 +257,15 @@
/**
* Removes a listener for observing the state of print jobs.
- *
+ *
* @param listener The listener to remove.
* @hide
*/
public void removePrintJobStateChangeListener(PrintJobStateChangeListener listener) {
+ if (mService == null) {
+ Log.w(LOG_TAG, "Feature android.software.print not available");
+ return;
+ }
if (mPrintJobStateChangeListeners == null) {
return;
}
@@ -275,12 +287,16 @@
/**
* Gets a print job given its id.
- *
+ *
* @return The print job list.
* @see PrintJob
* @hide
*/
public PrintJob getPrintJob(PrintJobId printJobId) {
+ if (mService == null) {
+ Log.w(LOG_TAG, "Feature android.software.print not available");
+ return null;
+ }
try {
PrintJobInfo printJob = mService.getPrintJobInfo(printJobId, mAppId, mUserId);
if (printJob != null) {
@@ -294,11 +310,15 @@
/**
* Gets the print jobs for this application.
- *
+ *
* @return The print job list.
* @see PrintJob
*/
public List<PrintJob> getPrintJobs() {
+ if (mService == null) {
+ Log.w(LOG_TAG, "Feature android.software.print not available");
+ return Collections.emptyList();
+ }
try {
List<PrintJobInfo> printJobInfos = mService.getPrintJobInfos(mAppId, mUserId);
if (printJobInfos == null) {
@@ -317,6 +337,10 @@
}
void cancelPrintJob(PrintJobId printJobId) {
+ if (mService == null) {
+ Log.w(LOG_TAG, "Feature android.software.print not available");
+ return;
+ }
try {
mService.cancelPrintJob(printJobId, mAppId, mUserId);
} catch (RemoteException re) {
@@ -325,6 +349,10 @@
}
void restartPrintJob(PrintJobId printJobId) {
+ if (mService == null) {
+ Log.w(LOG_TAG, "Feature android.software.print not available");
+ return;
+ }
try {
mService.restartPrintJob(printJobId, mAppId, mUserId);
} catch (RemoteException re) {
@@ -383,6 +411,10 @@
*/
public PrintJob print(String printJobName, PrintDocumentAdapter documentAdapter,
PrintAttributes attributes) {
+ if (mService == null) {
+ Log.w(LOG_TAG, "Feature android.software.print not available");
+ return null;
+ }
if (!(mContext instanceof Activity)) {
throw new IllegalStateException("Can print only from an activity");
}
@@ -418,11 +450,15 @@
/**
* Gets the list of enabled print services.
- *
+ *
* @return The enabled service list or an empty list.
* @hide
*/
public List<PrintServiceInfo> getEnabledPrintServices() {
+ if (mService == null) {
+ Log.w(LOG_TAG, "Feature android.software.print not available");
+ return Collections.emptyList();
+ }
try {
List<PrintServiceInfo> enabledServices = mService.getEnabledPrintServices(mUserId);
if (enabledServices != null) {
@@ -436,11 +472,15 @@
/**
* Gets the list of installed print services.
- *
+ *
* @return The installed service list or an empty list.
* @hide
*/
public List<PrintServiceInfo> getInstalledPrintServices() {
+ if (mService == null) {
+ Log.w(LOG_TAG, "Feature android.software.print not available");
+ return Collections.emptyList();
+ }
try {
List<PrintServiceInfo> installedServices = mService.getInstalledPrintServices(mUserId);
if (installedServices != null) {
@@ -456,6 +496,10 @@
* @hide
*/
public PrinterDiscoverySession createPrinterDiscoverySession() {
+ if (mService == null) {
+ Log.w(LOG_TAG, "Feature android.software.print not available");
+ return null;
+ }
return new PrinterDiscoverySession(mService, mContext, mUserId);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e0ac60b..1847b55 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2823,7 +2823,6 @@
MOVED_TO_GLOBAL.add(Settings.Global.TETHER_SUPPORTED);
MOVED_TO_GLOBAL.add(Settings.Global.USB_MASS_STORAGE_ENABLED);
MOVED_TO_GLOBAL.add(Settings.Global.USE_GOOGLE_MAIL);
- MOVED_TO_GLOBAL.add(Settings.Global.WEB_AUTOFILL_QUERY_URL);
MOVED_TO_GLOBAL.add(Settings.Global.WIFI_COUNTRY_CODE);
MOVED_TO_GLOBAL.add(Settings.Global.WIFI_FRAMEWORK_SCAN_INTERVAL_MS);
MOVED_TO_GLOBAL.add(Settings.Global.WIFI_FREQUENCY_BAND);
@@ -4530,6 +4529,12 @@
public static final String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component";
/**
+ * Whether NFC payment is handled by the foreground application or a default.
+ * @hide
+ */
+ public static final String NFC_PAYMENT_FOREGROUND = "nfc_payment_foreground";
+
+ /**
* Specifies the package name currently configured to be the primary sms application
* @hide
*/
@@ -5355,11 +5360,6 @@
*/
public static final String USE_GOOGLE_MAIL = "use_google_mail";
- /** Autofill server address (Used in WebView/browser).
- * {@hide} */
- public static final String WEB_AUTOFILL_QUERY_URL =
- "web_autofill_query_url";
-
/**
* Whether Wifi display is enabled/disabled
* 0=disabled. 1=enabled.
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 2549fde..49a0138 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -351,18 +351,8 @@
}
ArrayMap<View, TransitionValues> endCopy =
new ArrayMap<View, TransitionValues>(endValues.viewValues);
- SparseArray<TransitionValues> endIdCopy =
- new SparseArray<TransitionValues>(endValues.idValues.size());
- for (int i = 0; i < endValues.idValues.size(); ++i) {
- int id = endValues.idValues.keyAt(i);
- endIdCopy.put(id, endValues.idValues.valueAt(i));
- }
- LongSparseArray<TransitionValues> endItemIdCopy =
- new LongSparseArray<TransitionValues>(endValues.itemIdValues.size());
- for (int i = 0; i < endValues.itemIdValues.size(); ++i) {
- long id = endValues.itemIdValues.keyAt(i);
- endItemIdCopy.put(id, endValues.itemIdValues.valueAt(i));
- }
+ SparseArray<TransitionValues> endIdCopy = endValues.idValues.clone();
+ LongSparseArray<TransitionValues> endItemIdCopy = endValues.itemIdValues.clone();
// Walk through the start values, playing everything we find
// Remove from the end set as we go
ArrayList<TransitionValues> startValuesList = new ArrayList<TransitionValues>();
@@ -376,21 +366,17 @@
}
if (!isInListView) {
int id = view.getId();
- start = startValues.viewValues.get(view) != null ?
- startValues.viewValues.get(view) : startValues.idValues.get(id);
- if (endValues.viewValues.get(view) != null) {
- end = endValues.viewValues.get(view);
+ start = startValues.viewValues.get(view);
+ end = endValues.viewValues.get(view);
+ if (end != null) {
endCopy.remove(view);
} else if (id != View.NO_ID) {
- end = endValues.idValues.get(id);
- View removeView = null;
- for (View viewToRemove : endCopy.keySet()) {
- if (viewToRemove.getId() == id) {
- removeView = viewToRemove;
- }
- }
- if (removeView != null) {
- endCopy.remove(removeView);
+ end = endIdCopy.get(id);
+ if (end == null || startValues.viewValues.containsKey(end.view)) {
+ end = null;
+ id = View.NO_ID;
+ } else {
+ endCopy.remove(end.view);
}
}
endIdCopy.remove(id);
@@ -423,36 +409,16 @@
}
}
// Now walk through the remains of the end set
+ // We've already matched everything from start to end, everything else doesn't match.
for (View view : endCopy.keySet()) {
int id = view.getId();
if (isValidTarget(view, id)) {
- TransitionValues start = startValues.viewValues.get(view) != null ?
- startValues.viewValues.get(view) : startValues.idValues.get(id);
+ TransitionValues start = null;
TransitionValues end = endCopy.get(view);
- endIdCopy.remove(id);
startValuesList.add(start);
endValuesList.add(end);
}
}
- int endIdCopySize = endIdCopy.size();
- for (int i = 0; i < endIdCopySize; ++i) {
- int id = endIdCopy.keyAt(i);
- if (isValidTarget(null, id)) {
- TransitionValues start = startValues.idValues.get(id);
- TransitionValues end = endIdCopy.get(id);
- startValuesList.add(start);
- endValuesList.add(end);
- }
- }
- int endItemIdCopySize = endItemIdCopy.size();
- for (int i = 0; i < endItemIdCopySize; ++i) {
- long id = endItemIdCopy.keyAt(i);
- // TODO: Deal with targetIDs and itemIDs
- TransitionValues start = startValues.itemIdValues.get(id);
- TransitionValues end = endItemIdCopy.get(id);
- startValuesList.add(start);
- endValuesList.add(end);
- }
ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
long minStartDelay = Long.MAX_VALUE;
int minAnimator = mAnimators.size();
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index f234baa..6c451eb 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -43,7 +43,6 @@
class GLES20Canvas extends HardwareCanvas {
// Must match modifiers used in the JNI layer
private static final int MODIFIER_NONE = 0;
- private static final int MODIFIER_SHADOW = 1;
private static final int MODIFIER_SHADER = 2;
private final boolean mOpaque;
@@ -1297,12 +1296,6 @@
private int setupModifiers(Paint paint) {
int modifiers = MODIFIER_NONE;
- if (paint.hasShadow) {
- nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
- paint.shadowColor);
- modifiers |= MODIFIER_SHADOW;
- }
-
final Shader shader = paint.getShader();
if (shader != null) {
nSetupShader(mRenderer, shader.native_shader);
@@ -1315,12 +1308,6 @@
private int setupModifiers(Paint paint, int flags) {
int modifiers = MODIFIER_NONE;
- if (paint.hasShadow && (flags & MODIFIER_SHADOW) != 0) {
- nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
- paint.shadowColor);
- modifiers |= MODIFIER_SHADOW;
- }
-
final Shader shader = paint.getShader();
if (shader != null && (flags & MODIFIER_SHADER) != 0) {
nSetupShader(mRenderer, shader.native_shader);
@@ -1331,8 +1318,6 @@
}
private static native void nSetupShader(long renderer, long shader);
- private static native void nSetupShadow(long renderer, float radius,
- float dx, float dy, int color);
private static native void nResetModifiers(long renderer, int modifiers);
}
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 05e202b..2d1016a 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1685,10 +1685,6 @@
case KeyEvent.KEYCODE_BRIGHTNESS_DOWN:
case KeyEvent.KEYCODE_BRIGHTNESS_UP:
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- case KeyEvent.KEYCODE_DPAD_LEFT:
return true;
}
diff --git a/core/java/android/view/inputmethod/CorrectionInfo.java b/core/java/android/view/inputmethod/CorrectionInfo.java
index 1b04e49..a43dfe8 100644
--- a/core/java/android/view/inputmethod/CorrectionInfo.java
+++ b/core/java/android/view/inputmethod/CorrectionInfo.java
@@ -88,16 +88,15 @@
/**
* Used to make this class parcelable.
*/
- public static final Parcelable.Creator<CorrectionInfo> CREATOR
- = new Parcelable.Creator<CorrectionInfo>() {
- public CorrectionInfo createFromParcel(Parcel source) {
- return new CorrectionInfo(source);
- }
-
- public CorrectionInfo[] newArray(int size) {
- return new CorrectionInfo[size];
- }
- };
+ public static final Parcelable.Creator<CorrectionInfo> CREATOR =
+ new Parcelable.Creator<CorrectionInfo>() {
+ public CorrectionInfo createFromParcel(Parcel source) {
+ return new CorrectionInfo(source);
+ }
+ public CorrectionInfo[] newArray(int size) {
+ return new CorrectionInfo[size];
+ }
+ };
public int describeContents() {
return 0;
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.aidl b/core/java/android/view/inputmethod/CursorAnchorInfo.aidl
new file mode 100644
index 0000000..2ee9edb
--- /dev/null
+++ b/core/java/android/view/inputmethod/CursorAnchorInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+parcelable CursorAnchorInfo;
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java
new file mode 100644
index 0000000..92455df
--- /dev/null
+++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java
@@ -0,0 +1,449 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.view.inputmethod;
+
+import android.graphics.Matrix;
+import android.graphics.RectF;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.Layout;
+import android.view.inputmethod.SparseRectFArray.SparseRectFArrayBuilder;
+
+import java.util.Objects;
+
+/**
+ * Positional information about the text insertion point and characters in the composition string.
+ *
+ * <p>This class encapsulates locations of the text insertion point and the composition string in
+ * the screen coordinates so that IMEs can render their UI components near where the text is
+ * actually inserted.</p>
+ */
+public final class CursorAnchorInfo implements Parcelable {
+ private final int mSelectionStart;
+ private final int mSelectionEnd;
+ private final int mCandidatesStart;
+ private final int mCandidatesEnd;
+
+ /**
+ * Horizontal position of the insertion marker, in the local coordinates that will be
+ * transformed with the transformation matrix when rendered on the screen. This should be
+ * calculated or compatible with {@link Layout#getPrimaryHorizontal(int)}. This can be
+ * {@code java.lang.Float.NaN} when no value is specified.
+ */
+ private final float mInsertionMarkerHorizontal;
+ /**
+ * Vertical position of the insertion marker, in the local coordinates that will be
+ * transformed with the transformation matrix when rendered on the screen. This should be
+ * calculated or compatible with {@link Layout#getLineTop(int)}. This can be
+ * {@code java.lang.Float.NaN} when no value is specified.
+ */
+ private final float mInsertionMarkerTop;
+ /**
+ * Vertical position of the insertion marker, in the local coordinates that will be
+ * transformed with the transformation matrix when rendered on the screen. This should be
+ * calculated or compatible with {@link Layout#getLineBaseline(int)}. This can be
+ * {@code java.lang.Float.NaN} when no value is specified.
+ */
+ private final float mInsertionMarkerBaseline;
+ /**
+ * Vertical position of the insertion marker, in the local coordinates that will be
+ * transformed with the transformation matrix when rendered on the screen. This should be
+ * calculated or compatible with {@link Layout#getLineBottom(int)}. This can be
+ * {@code java.lang.Float.NaN} when no value is specified.
+ */
+ private final float mInsertionMarkerBottom;
+
+ /**
+ * Container of rectangular position of characters, keyed with character index in a unit of
+ * Java chars, in the local coordinates that will be transformed with the transformation matrix
+ * when rendered on the screen.
+ */
+ private final SparseRectFArray mCharacterRects;
+
+ /**
+ * Transformation matrix that is applied to any positional information of this class to
+ * transform local coordinates into screen coordinates.
+ */
+ private final Matrix mMatrix;
+
+ public CursorAnchorInfo(final Parcel source) {
+ mSelectionStart = source.readInt();
+ mSelectionEnd = source.readInt();
+ mCandidatesStart = source.readInt();
+ mCandidatesEnd = source.readInt();
+ mInsertionMarkerHorizontal = source.readFloat();
+ mInsertionMarkerTop = source.readFloat();
+ mInsertionMarkerBaseline = source.readFloat();
+ mInsertionMarkerBottom = source.readFloat();
+ mCharacterRects = source.readParcelable(SparseRectFArray.class.getClassLoader());
+ mMatrix = new Matrix();
+ mMatrix.setValues(source.createFloatArray());
+ }
+
+ /**
+ * Used to package this object into a {@link Parcel}.
+ *
+ * @param dest The {@link Parcel} to be written.
+ * @param flags The flags used for parceling.
+ */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mSelectionStart);
+ dest.writeInt(mSelectionEnd);
+ dest.writeInt(mCandidatesStart);
+ dest.writeInt(mCandidatesEnd);
+ dest.writeFloat(mInsertionMarkerHorizontal);
+ dest.writeFloat(mInsertionMarkerTop);
+ dest.writeFloat(mInsertionMarkerBaseline);
+ dest.writeFloat(mInsertionMarkerBottom);
+ dest.writeParcelable(mCharacterRects, flags);
+ final float[] matrixArray = new float[9];
+ mMatrix.getValues(matrixArray);
+ dest.writeFloatArray(matrixArray);
+ }
+
+ @Override
+ public int hashCode(){
+ // TODO: Improve the hash function.
+ final float floatHash = mSelectionStart + mSelectionEnd + mCandidatesStart + mCandidatesEnd
+ + mInsertionMarkerHorizontal + mInsertionMarkerTop + mInsertionMarkerBaseline
+ + mInsertionMarkerBottom;
+ int hash = floatHash > 0 ? (int) floatHash : (int)(-floatHash);
+ if (mCharacterRects != null) {
+ hash += mCharacterRects.hashCode();
+ }
+ hash += mMatrix.hashCode();
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj){
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof CursorAnchorInfo)) {
+ return false;
+ }
+ final CursorAnchorInfo that = (CursorAnchorInfo) obj;
+ if (hashCode() != that.hashCode()) {
+ return false;
+ }
+ if (mSelectionStart != that.mSelectionStart
+ || mSelectionEnd != that.mSelectionEnd
+ || mCandidatesStart != that.mCandidatesStart
+ || mCandidatesEnd != that.mCandidatesEnd) {
+ return false;
+ }
+ if (!Objects.equals(mCharacterRects, that.mCharacterRects)) {
+ return false;
+ }
+ if (!Objects.equals(mMatrix, that.mMatrix)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "SelectionInfo{mSelection=" + mSelectionStart + "," + mSelectionEnd
+ + " mCandiadtes=" + mCandidatesStart + "," + mCandidatesEnd
+ + " mInsertionMarkerHorizontal=" + mInsertionMarkerHorizontal
+ + " mInsertionMarkerTop=" + mInsertionMarkerTop
+ + " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline
+ + " mInsertionMarkerBottom=" + mInsertionMarkerBottom
+ + " mCharacterRects=" + (mCharacterRects != null ? mCharacterRects : "null")
+ + " mMatrix=" + mMatrix
+ + "}";
+ }
+
+ /**
+ * Builder for {@link CursorAnchorInfo}. This class is not designed to be thread-safe.
+ */
+ public static final class CursorAnchorInfoBuilder {
+ /**
+ * Sets the text range of the selection. Calling this can be skipped if there is no
+ * selection.
+ */
+ public CursorAnchorInfoBuilder setSelectionRange(final int newStart, final int newEnd) {
+ mSelectionStart = newStart;
+ mSelectionEnd = newEnd;
+ return this;
+ }
+ private int mSelectionStart = -1;
+ private int mSelectionEnd = -1;
+
+ /**
+ * Sets the text range of the composition string. Calling this can be skipped if there is
+ * no composition.
+ */
+ public CursorAnchorInfoBuilder setCandidateRange(final int start, final int end) {
+ mCandidateStart = start;
+ mCandidateEnd = end;
+ return this;
+ }
+ private int mCandidateStart = -1;
+ private int mCandidateEnd = -1;
+
+ /**
+ * Sets the location of the text insertion point (zero width cursor) as a rectangle in
+ * local coordinates. Calling this can be skipped when there is no text insertion point;
+ * however if there is an insertion point, editors must call this method.
+ * @param horizontalPosition horizontal position of the insertion marker, in the local
+ * coordinates that will be transformed with the transformation matrix when rendered on the
+ * screen. This should be calculated or compatible with
+ * {@link Layout#getPrimaryHorizontal(int)}.
+ * @param lineTop vertical position of the insertion marker, in the local coordinates that
+ * will be transformed with the transformation matrix when rendered on the screen. This
+ * should be calculated or compatible with {@link Layout#getLineTop(int)}.
+ * @param lineBaseline vertical position of the insertion marker, in the local coordinates
+ * that will be transformed with the transformation matrix when rendered on the screen. This
+ * should be calculated or compatible with {@link Layout#getLineBaseline(int)}.
+ * @param lineBottom vertical position of the insertion marker, in the local coordinates
+ * that will be transformed with the transformation matrix when rendered on the screen. This
+ * should be calculated or compatible with {@link Layout#getLineBottom(int)}.
+ */
+ public CursorAnchorInfoBuilder setInsertionMarkerLocation(
+ final float horizontalPosition, final float lineTop, final float lineBaseline,
+ final float lineBottom){
+ mInsertionMarkerHorizontal = horizontalPosition;
+ mInsertionMarkerTop = lineTop;
+ mInsertionMarkerBaseline = lineBaseline;
+ mInsertionMarkerBottom = lineBottom;
+ return this;
+ }
+ private float mInsertionMarkerHorizontal = Float.NaN;
+ private float mInsertionMarkerTop = Float.NaN;
+ private float mInsertionMarkerBaseline = Float.NaN;
+ private float mInsertionMarkerBottom = Float.NaN;
+
+ /**
+ * Adds the bounding box of the character specified with the index.
+ * <p>
+ * Editor authors should not call this method for characters that are invisible.
+ * </p>
+ *
+ * @param index index of the character in Java chars units. Must be specified in
+ * ascending order across successive calls.
+ * @param leadingEdgeX x coordinate of the leading edge of the character in local
+ * coordinates, that is, left edge for LTR text and right edge for RTL text.
+ * @param leadingEdgeY y coordinate of the leading edge of the character in local
+ * coordinates.
+ * @param trailingEdgeX x coordinate of the trailing edge of the character in local
+ * coordinates, that is, right edge for LTR text and left edge for RTL text.
+ * @param trailingEdgeY y coordinate of the trailing edge of the character in local
+ * coordinates.
+ * @throws IllegalArgumentException If the index is a negative value, or not greater than
+ * all of the previously called indices.
+ */
+ public CursorAnchorInfoBuilder addCharacterRect(final int index,
+ final float leadingEdgeX, final float leadingEdgeY, final float trailingEdgeX,
+ final float trailingEdgeY) {
+ if (index < 0) {
+ throw new IllegalArgumentException("index must not be a negative integer.");
+ }
+ if (mCharacterRectBuilder == null) {
+ mCharacterRectBuilder = new SparseRectFArrayBuilder();
+ }
+ mCharacterRectBuilder.append(index, leadingEdgeX, leadingEdgeY, trailingEdgeX,
+ trailingEdgeY);
+ return this;
+ }
+ private SparseRectFArrayBuilder mCharacterRectBuilder = null;
+
+ /**
+ * Sets the matrix that transforms local coordinates into screen coordinates.
+ * @param matrix transformation matrix from local coordinates into screen coordinates. null
+ * is interpreted as an identity matrix.
+ */
+ public CursorAnchorInfoBuilder setMatrix(final Matrix matrix) {
+ if (matrix != null) {
+ mMatrix = matrix;
+ } else {
+ mMatrix = Matrix.IDENTITY_MATRIX;
+ }
+ return this;
+ }
+ private Matrix mMatrix = Matrix.IDENTITY_MATRIX;
+
+ /**
+ * @return {@link CursorAnchorInfo} using parameters in this
+ * {@link CursorAnchorInfoBuilder}.
+ */
+ public CursorAnchorInfo build() {
+ return new CursorAnchorInfo(this);
+ }
+
+ /**
+ * Resets the internal state so that this instance can be reused to build another
+ * instance of {@link CursorAnchorInfo}.
+ */
+ public void reset() {
+ mSelectionStart = -1;
+ mSelectionEnd = -1;
+ mCandidateStart = -1;
+ mCandidateEnd = -1;
+ mInsertionMarkerHorizontal = Float.NaN;
+ mInsertionMarkerTop = Float.NaN;
+ mInsertionMarkerBaseline = Float.NaN;
+ mInsertionMarkerBottom = Float.NaN;
+ mMatrix = Matrix.IDENTITY_MATRIX;
+ if (mCharacterRectBuilder != null) {
+ mCharacterRectBuilder.reset();
+ }
+ }
+ }
+
+ private CursorAnchorInfo(final CursorAnchorInfoBuilder builder) {
+ mSelectionStart = builder.mSelectionStart;
+ mSelectionEnd = builder.mSelectionEnd;
+ mCandidatesStart = builder.mCandidateStart;
+ mCandidatesEnd = builder.mCandidateEnd;
+ mInsertionMarkerHorizontal = builder.mInsertionMarkerHorizontal;
+ mInsertionMarkerTop = builder.mInsertionMarkerTop;
+ mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline;
+ mInsertionMarkerBottom = builder.mInsertionMarkerBottom;
+ mCharacterRects = builder.mCharacterRectBuilder != null ?
+ builder.mCharacterRectBuilder.build() : null;
+ mMatrix = builder.mMatrix;
+ }
+
+ /**
+ * Returns the index where the selection starts.
+ * @return -1 if there is no selection.
+ */
+ public int getSelectionStart() {
+ return mSelectionStart;
+ }
+
+ /**
+ * Returns the index where the selection ends.
+ * @return -1 if there is no selection.
+ */
+ public int getSelectionEnd() {
+ return mSelectionEnd;
+ }
+
+ /**
+ * Returns the index where the composition starts.
+ * @return -1 if there is no composition.
+ */
+ public int getCandidatesStart() {
+ return mCandidatesStart;
+ }
+
+ /**
+ * Returns the index where the composition ends.
+ * @return -1 if there is no composition.
+ */
+ public int getCandidatesEnd() {
+ return mCandidatesEnd;
+ }
+
+ /**
+ * Returns the horizontal start of the insertion marker, in the local coordinates that will
+ * be transformed with {@link #getMatrix()} when rendered on the screen.
+ * @return x coordinate that is compatible with {@link Layout#getPrimaryHorizontal(int)}.
+ * Pay special care to RTL/LTR handling.
+ * {@code java.lang.Float.NaN} if not specified.
+ * @see Layout#getPrimaryHorizontal(int)
+ */
+ public float getInsertionMarkerHorizontal() {
+ return mInsertionMarkerHorizontal;
+ }
+ /**
+ * Returns the vertical top position of the insertion marker, in the local coordinates that
+ * will be transformed with {@link #getMatrix()} when rendered on the screen.
+ * @return y coordinate that is compatible with {@link Layout#getLineTop(int)}.
+ * {@code java.lang.Float.NaN} if not specified.
+ */
+ public float getInsertionMarkerTop() {
+ return mInsertionMarkerTop;
+ }
+ /**
+ * Returns the vertical baseline position of the insertion marker, in the local coordinates
+ * that will be transformed with {@link #getMatrix()} when rendered on the screen.
+ * @return y coordinate that is compatible with {@link Layout#getLineBaseline(int)}.
+ * {@code java.lang.Float.NaN} if not specified.
+ */
+ public float getInsertionMarkerBaseline() {
+ return mInsertionMarkerBaseline;
+ }
+ /**
+ * Returns the vertical bottom position of the insertion marker, in the local coordinates
+ * that will be transformed with {@link #getMatrix()} when rendered on the screen.
+ * @return y coordinate that is compatible with {@link Layout#getLineBottom(int)}.
+ * {@code java.lang.Float.NaN} if not specified.
+ */
+ public float getInsertionMarkerBottom() {
+ return mInsertionMarkerBottom;
+ }
+
+ /**
+ * Returns a new instance of {@link RectF} that indicates the location of the character
+ * specified with the index.
+ * <p>
+ * Note that coordinates are not necessarily contiguous or even monotonous, especially when
+ * RTL text and LTR text are mixed.
+ * </p>
+ * @param index index of the character in a Java chars.
+ * @return a new instance of {@link RectF} that represents the location of the character in
+ * local coordinates. null if the character is invisible or the application did not provide
+ * the location. Note that the {@code left} field can be greater than the {@code right} field
+ * if the character is in RTL text.
+ */
+ // TODO: Prepare a document about the expected behavior for surrogate pairs, combining
+ // characters, and non-graphical chars.
+ public RectF getCharacterRect(final int index) {
+ if (mCharacterRects == null) {
+ return null;
+ }
+ return mCharacterRects.get(index);
+ }
+
+ /**
+ * Returns a new instance of {@link android.graphics.Matrix} that indicates the transformation
+ * matrix that is to be applied other positional data in this class.
+ * @return a new instance (copy) of the transformation matrix.
+ */
+ public Matrix getMatrix() {
+ return new Matrix(mMatrix);
+ }
+
+ /**
+ * Used to make this class parcelable.
+ */
+ public static final Parcelable.Creator<CursorAnchorInfo> CREATOR
+ = new Parcelable.Creator<CursorAnchorInfo>() {
+ @Override
+ public CursorAnchorInfo createFromParcel(Parcel source) {
+ return new CursorAnchorInfo(source);
+ }
+
+ @Override
+ public CursorAnchorInfo[] newArray(int size) {
+ return new CursorAnchorInfo[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 0227873..e1c6f52 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -49,6 +49,7 @@
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewRootImpl;
+import android.view.inputmethod.CursorAnchorInfo.CursorAnchorInfoBuilder;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -321,6 +322,7 @@
* The buffer to retrieve the view location in screen coordinates in {@link #updateCursor}.
*/
private final int[] mViewTopLeft = new int[2];
+ private final CursorAnchorInfoBuilder mCursorAnchorInfoBuilder = new CursorAnchorInfoBuilder();
// -----------------------------------------------------------
@@ -1435,7 +1437,7 @@
|| mCurrentTextBoxAttribute == null || mCurMethod == null) {
return;
}
-
+
if (mCursorSelStart != selStart || mCursorSelEnd != selEnd
|| mCursorCandStart != candidatesStart
|| mCursorCandEnd != candidatesEnd) {
@@ -1556,6 +1558,31 @@
}
/**
+ * Report positional change of the text insertion point and/or characters in the composition
+ * string.
+ */
+ public void updateCursorAnchorInfo(View view, final CursorAnchorInfo cursorAnchorInfo) {
+ if (view == null || cursorAnchorInfo == null) {
+ return;
+ }
+ checkFocus();
+ synchronized (mH) {
+ if ((mServedView != view &&
+ (mServedView == null || !mServedView.checkInputConnectionProxy(view)))
+ || mCurrentTextBoxAttribute == null || mCurMethod == null) {
+ return;
+ }
+ if (DEBUG) Log.d(TAG, "updateCursorAnchorInfo");
+
+ try {
+ mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo);
+ } catch (RemoteException e) {
+ Log.w(TAG, "IME died: " + mCurId, e);
+ }
+ }
+ }
+
+ /**
* Call {@link InputMethodSession#appPrivateCommand(String, Bundle)
* InputMethodSession.appPrivateCommand()} on the current Input Method.
* @param view Optional View that is sending the command, or null if
diff --git a/core/java/android/view/inputmethod/InputMethodSession.java b/core/java/android/view/inputmethod/InputMethodSession.java
index 6386299..74fbbc7 100644
--- a/core/java/android/view/inputmethod/InputMethodSession.java
+++ b/core/java/android/view/inputmethod/InputMethodSession.java
@@ -165,7 +165,7 @@
public void appPrivateCommand(String action, Bundle data);
/**
- * Toggle the soft input window.
+ * Toggle the soft input window.
* Applications can toggle the state of the soft input window.
* @param showFlags Provides additional operating flags. May be
* 0 or have the {@link InputMethodManager#SHOW_IMPLICIT},
@@ -175,4 +175,14 @@
* {@link InputMethodManager#HIDE_NOT_ALWAYS} bit set.
*/
public void toggleSoftInput(int showFlags, int hideFlags);
+
+ /**
+ * This method is called when the cursor and/or the character position relevant to text input
+ * is changed on the screen. This is not called by default. It will only be reported if
+ * requested by the input method.
+ *
+ * @param cursorAnchorInfo Positional information relevant to text input, such as text
+ * insertion point and composition string.
+ */
+ public void updateCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo);
}
diff --git a/core/java/android/view/inputmethod/SparseRectFArray.java b/core/java/android/view/inputmethod/SparseRectFArray.java
new file mode 100644
index 0000000..40cade7
--- /dev/null
+++ b/core/java/android/view/inputmethod/SparseRectFArray.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.view.inputmethod;
+
+import android.graphics.RectF;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+
+/**
+ * An implementation of SparseArray specialized for {@link android.graphics.RectF}.
+ * <p>
+ * As this is a sparse array, it represents an array of {@link RectF} most of which are null. This
+ * class could be in some other packages like android.graphics or android.util but currently
+ * belong to android.view.inputmethod because this class is hidden and used only in input method
+ * framework.
+ * </p>
+ * @hide
+ */
+public final class SparseRectFArray implements Parcelable {
+ /**
+ * The keys, in ascending order, of those {@link RectF} that are not null. For example,
+ * {@code [null, null, null, Rect1, null, Rect2]} would be represented by {@code [3,5]}.
+ * @see #mCoordinates
+ */
+ private final int[] mKeys;
+
+ /**
+ * Stores coordinates of the rectangles, in the order of
+ * {@code rects[mKeys[0]].left}, {@code rects[mKeys[0]].top},
+ * {@code rects[mKeys[0]].right}, {@code rects[mKeys[0]].bottom},
+ * {@code rects[mKeys[1]].left}, {@code rects[mKeys[1]].top},
+ * {@code rects[mKeys[1]].right}, {@code rects[mKeys[1]].bottom},
+ * {@code rects[mKeys[2]].left}, {@code rects[mKeys[2]].top}, ....
+ */
+ private final float[] mCoordinates;
+
+ public SparseRectFArray(final Parcel source) {
+ mKeys = source.createIntArray();
+ mCoordinates = source.createFloatArray();
+ }
+
+ /**
+ * Used to package this object into a {@link Parcel}.
+ *
+ * @param dest The {@link Parcel} to be written.
+ * @param flags The flags used for parceling.
+ */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeIntArray(mKeys);
+ dest.writeFloatArray(mCoordinates);
+ }
+
+ @Override
+ public int hashCode() {
+ // TODO: Improve the hash function.
+ if (mKeys == null || mKeys.length == 0) {
+ return 0;
+ }
+ int hash = mKeys.length;
+ // For performance reasons, only the first rectangle is used for the hash code now.
+ for (int i = 0; i < 4; i++) {
+ hash *= 31;
+ hash += mCoordinates[i];
+ }
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj){
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof SparseRectFArray)) {
+ return false;
+ }
+ final SparseRectFArray that = (SparseRectFArray) obj;
+
+ return Arrays.equals(mKeys, that.mKeys) && Arrays.equals(mCoordinates, that.mCoordinates);
+ }
+
+ @Override
+ public String toString() {
+ if (mKeys == null || mCoordinates == null) {
+ return "SparseRectFArray{}";
+ }
+ final StringBuilder sb = new StringBuilder();
+ sb.append("SparseRectFArray{");
+ for (int i = 0; i < mKeys.length; i++) {
+ if (i != 0) {
+ sb.append(", ");
+ }
+ final int baseIndex = i * 4;
+ sb.append(mKeys[i]);
+ sb.append(":[");
+ sb.append(mCoordinates[baseIndex + 0]);
+ sb.append(",");
+ sb.append(mCoordinates[baseIndex + 1]);
+ sb.append("],[");
+ sb.append(mCoordinates[baseIndex + 2]);
+ sb.append(",");
+ sb.append(mCoordinates[baseIndex + 3]);
+ sb.append("]");
+ }
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Builder for {@link SparseRectFArray}. This class is not designed to be thread-safe.
+ * @hide
+ */
+ public static final class SparseRectFArrayBuilder {
+ /**
+ * Throws {@link IllegalArgumentException} to make sure that this class is correctly used.
+ * @param key key to be checked.
+ */
+ private void checkIndex(final int key) {
+ if (mCount == 0) {
+ return;
+ }
+ if (mKeys[mCount - 1] >= key) {
+ throw new IllegalArgumentException("key must be greater than all existing keys.");
+ }
+ }
+
+ /**
+ * Extends the internal array if necessary.
+ */
+ private void ensureBufferSize() {
+ if (mKeys == null) {
+ mKeys = new int[INITIAL_SIZE];
+ }
+ if (mCoordinates == null) {
+ mCoordinates = new float[INITIAL_SIZE * 4];
+ }
+ final int requiredIndexArraySize = mCount + 1;
+ if (mKeys.length <= requiredIndexArraySize) {
+ final int[] newArray = new int[requiredIndexArraySize * 2];
+ System.arraycopy(mKeys, 0, newArray, 0, mCount);
+ mKeys = newArray;
+ }
+ final int requiredCoordinatesArraySize = (mCount + 1) * 4;
+ if (mCoordinates.length <= requiredCoordinatesArraySize) {
+ final float[] newArray = new float[requiredCoordinatesArraySize * 2];
+ System.arraycopy(mCoordinates, 0, newArray, 0, mCount * 4);
+ mCoordinates = newArray;
+ }
+ }
+
+ /**
+ * Puts the rectangle with an integer key.
+ * @param key the key to be associated with the rectangle. It must be greater than all
+ * existing keys that have been previously specified.
+ * @param left left of the rectangle.
+ * @param top top of the rectangle.
+ * @param right right of the rectangle.
+ * @param bottom bottom of the rectangle.
+ * @return the receiver object itself for chaining method calls.
+ * @throws IllegalArgumentException If the index is not greater than all of existing keys.
+ */
+ public SparseRectFArrayBuilder append(final int key,
+ final float left, final float top, final float right, final float bottom) {
+ checkIndex(key);
+ ensureBufferSize();
+ final int baseCoordinatesIndex = mCount * 4;
+ mCoordinates[baseCoordinatesIndex + 0] = left;
+ mCoordinates[baseCoordinatesIndex + 1] = top;
+ mCoordinates[baseCoordinatesIndex + 2] = right;
+ mCoordinates[baseCoordinatesIndex + 3] = bottom;
+ mKeys[mCount] = key;
+ ++mCount;
+ return this;
+ }
+ private int mCount = 0;
+ private int[] mKeys = null;
+ private float[] mCoordinates = null;
+ private static int INITIAL_SIZE = 16;
+
+ /**
+ * @return {@link SparseRectFArray} using parameters in this {@link SparseRectFArray}.
+ */
+ public SparseRectFArray build() {
+ return new SparseRectFArray(this);
+ }
+
+ public void reset() {
+ if (mCount == 0) {
+ mKeys = null;
+ mCoordinates = null;
+ }
+ mCount = 0;
+ }
+ }
+
+ private SparseRectFArray(final SparseRectFArrayBuilder builder) {
+ if (builder.mCount == 0) {
+ mKeys = null;
+ mCoordinates = null;
+ } else {
+ mKeys = new int[builder.mCount];
+ mCoordinates = new float[builder.mCount * 4];
+ System.arraycopy(builder.mKeys, 0, mKeys, 0, builder.mCount);
+ System.arraycopy(builder.mCoordinates, 0, mCoordinates, 0, builder.mCount * 4);
+ }
+ }
+
+ public RectF get(final int index) {
+ if (mKeys == null) {
+ return null;
+ }
+ if (index < 0) {
+ return null;
+ }
+ final int arrayIndex = Arrays.binarySearch(mKeys, index);
+ if (arrayIndex < 0) {
+ return null;
+ }
+ final int baseCoordIndex = arrayIndex * 4;
+ return new RectF(mCoordinates[baseCoordIndex],
+ mCoordinates[baseCoordIndex + 1],
+ mCoordinates[baseCoordIndex + 2],
+ mCoordinates[baseCoordIndex + 3]);
+ }
+
+ /**
+ * Used to make this class parcelable.
+ */
+ public static final Parcelable.Creator<SparseRectFArray> CREATOR =
+ new Parcelable.Creator<SparseRectFArray>() {
+ @Override
+ public SparseRectFArray createFromParcel(Parcel source) {
+ return new SparseRectFArray(source);
+ }
+ @Override
+ public SparseRectFArray[] newArray(int size) {
+ return new SparseRectFArray[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
+
diff --git a/core/java/android/webkit/EventLogTags.logtags b/core/java/android/webkit/EventLogTags.logtags
index b0b5493..a90aebd 100644
--- a/core/java/android/webkit/EventLogTags.logtags
+++ b/core/java/android/webkit/EventLogTags.logtags
@@ -8,3 +8,4 @@
# 70103- used by the browser app itself
70150 browser_snap_center
+70151 exp_det_attempt_to_call_object_getclass (app_signature|3)
diff --git a/core/java/android/webkit/PermissionRequest.java b/core/java/android/webkit/PermissionRequest.java
index 3e33498..fa760b7 100644
--- a/core/java/android/webkit/PermissionRequest.java
+++ b/core/java/android/webkit/PermissionRequest.java
@@ -28,6 +28,7 @@
public interface PermissionRequest {
/**
* Resource belongs to geolocation service.
+ * @hide - see b/14668406
*/
public final static long RESOURCE_GEOLOCATION = 1 << 0;
/**
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index e4ad354..99a7886 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -276,8 +276,13 @@
* @see Intent#ACTION_SEND_MULTIPLE
*/
public void setShareIntent(Intent shareIntent) {
- shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
+ if (shareIntent != null) {
+ final String action = shareIntent.getAction();
+ if (Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+ shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS);
+ }
+ }
ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
mShareHistoryFileName);
dataModel.setIntent(shareIntent);
@@ -294,8 +299,12 @@
final int itemId = item.getItemId();
Intent launchIntent = dataModel.chooseActivity(itemId);
if (launchIntent != null) {
- launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
- Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS);
+ final String action = launchIntent.getAction();
+ if (Intent.ACTION_SEND.equals(action) ||
+ Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+ launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
+ Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS);
+ }
mContext.startActivity(launchIntent);
}
return true;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b91111d..8f073de 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -289,6 +289,8 @@
private Spannable.Factory mSpannableFactory = Spannable.Factory.getInstance();
private float mShadowRadius, mShadowDx, mShadowDy;
+ private int mShadowColor;
+
private boolean mPreDrawRegistered;
@@ -2755,6 +2757,7 @@
mShadowRadius = radius;
mShadowDx = dx;
mShadowDy = dy;
+ mShadowColor = color;
// Will change text clip region
if (mEditor != null) mEditor.invalidateTextDisplayList();
@@ -2804,7 +2807,7 @@
* @attr ref android.R.styleable#TextView_shadowColor
*/
public int getShadowColor() {
- return mTextPaint.shadowColor;
+ return mShadowColor;
}
/**
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 1eda373..106ac0b 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -33,6 +33,14 @@
return;
}
Intent target = (Intent)targetParcelable;
+ if (target != null) {
+ final String action = target.getAction();
+ if (Intent.ACTION_SEND.equals(action) ||
+ Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+ target.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
+ Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS);
+ }
+ }
CharSequence title = intent.getCharSequenceExtra(Intent.EXTRA_TITLE);
if (title == null) {
title = getResources().getText(com.android.internal.R.string.chooseActivity);
@@ -43,13 +51,19 @@
initialIntents = new Intent[pa.length];
for (int i=0; i<pa.length; i++) {
if (!(pa[i] instanceof Intent)) {
- Log.w("ChooserActivity", "Initial intent #" + i
- + " not an Intent: " + pa[i]);
+ Log.w("ChooserActivity", "Initial intent #" + i + " not an Intent: " + pa[i]);
finish();
super.onCreate(null);
return;
}
- initialIntents[i] = (Intent)pa[i];
+ final Intent in = (Intent) pa[i];
+ final String action = in.getAction();
+ if (Intent.ACTION_SEND.equals(action) ||
+ Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+ in.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
+ Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS);
+ }
+ initialIntents[i] = in;
}
}
super.onCreate(savedInstanceState, target, title, initialIntents, null, false);
diff --git a/core/java/com/android/internal/app/IUsageStats.aidl b/core/java/com/android/internal/app/IUsageStats.aidl
index 1ea7409..7e7f0e1 100644
--- a/core/java/com/android/internal/app/IUsageStats.aidl
+++ b/core/java/com/android/internal/app/IUsageStats.aidl
@@ -16,13 +16,17 @@
package com.android.internal.app;
+import android.app.UsageStats;
import android.content.ComponentName;
-import com.android.internal.os.PkgUsageStats;
+import android.content.res.Configuration;
+import android.os.ParcelableParcel;
interface IUsageStats {
void noteResumeComponent(in ComponentName componentName);
void notePauseComponent(in ComponentName componentName);
void noteLaunchTime(in ComponentName componentName, int millis);
- PkgUsageStats getPkgUsageStats(in ComponentName componentName);
- PkgUsageStats[] getAllPkgUsageStats();
+ void noteStartConfig(in Configuration config);
+ UsageStats.PackageStats getPkgUsageStats(String callingPkg, in ComponentName componentName);
+ UsageStats.PackageStats[] getAllPkgUsageStats(String callingPkg);
+ ParcelableParcel getCurrentStats(String callingPkg);
}
diff --git a/core/java/com/android/internal/os/PkgUsageStats.aidl b/core/java/com/android/internal/os/PkgUsageStats.aidl
deleted file mode 100644
index 8305271..0000000
--- a/core/java/com/android/internal/os/PkgUsageStats.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/content/Intent.aidl
-**
-** Copyright 2007, 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.internal.os;
-
-parcelable PkgUsageStats;
diff --git a/core/java/com/android/internal/os/PkgUsageStats.java b/core/java/com/android/internal/os/PkgUsageStats.java
deleted file mode 100644
index 8c2c405..0000000
--- a/core/java/com/android/internal/os/PkgUsageStats.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2009 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.internal.os;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * implementation of PkgUsageStats associated with an
- * application package.
- * @hide
- */
-public class PkgUsageStats implements Parcelable {
- public String packageName;
- public int launchCount;
- public long usageTime;
- public Map<String, Long> componentResumeTimes;
-
- public static final Parcelable.Creator<PkgUsageStats> CREATOR
- = new Parcelable.Creator<PkgUsageStats>() {
- public PkgUsageStats createFromParcel(Parcel in) {
- return new PkgUsageStats(in);
- }
-
- public PkgUsageStats[] newArray(int size) {
- return new PkgUsageStats[size];
- }
- };
-
- public String toString() {
- return "PkgUsageStats{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + packageName + "}";
- }
-
- public PkgUsageStats(String pkgName, int count, long time, Map<String, Long> lastResumeTimes) {
- packageName = pkgName;
- launchCount = count;
- usageTime = time;
- componentResumeTimes = new HashMap<String, Long>(lastResumeTimes);
- }
-
- public PkgUsageStats(Parcel source) {
- packageName = source.readString();
- launchCount = source.readInt();
- usageTime = source.readLong();
- final int N = source.readInt();
- componentResumeTimes = new HashMap<String, Long>(N);
- for (int i = 0; i < N; i++) {
- String component = source.readString();
- long lastResumeTime = source.readLong();
- componentResumeTimes.put(component, lastResumeTime);
- }
- }
-
- public PkgUsageStats(PkgUsageStats pStats) {
- packageName = pStats.packageName;
- launchCount = pStats.launchCount;
- usageTime = pStats.usageTime;
- componentResumeTimes = new HashMap<String, Long>(pStats.componentResumeTimes);
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags) {
- dest.writeString(packageName);
- dest.writeInt(launchCount);
- dest.writeLong(usageTime);
- dest.writeInt(componentResumeTimes.size());
- for (Map.Entry<String, Long> ent : componentResumeTimes.entrySet()) {
- dest.writeString(ent.getKey());
- dest.writeLong(ent.getValue());
- }
- }
-}
diff --git a/core/java/com/android/internal/view/IInputMethodSession.aidl b/core/java/com/android/internal/view/IInputMethodSession.aidl
index 90210ce..367b713 100644
--- a/core/java/com/android/internal/view/IInputMethodSession.aidl
+++ b/core/java/com/android/internal/view/IInputMethodSession.aidl
@@ -21,6 +21,7 @@
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.CursorAnchorInfo;
import android.view.inputmethod.ExtractedText;
/**
@@ -47,4 +48,6 @@
void toggleSoftInput(int showFlags, int hideFlags);
void finishSession();
+
+ void updateCursorAnchorInfo(in CursorAnchorInfo cursorAnchorInfo);
}
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
index 674d084..bcfa036 100644
--- a/core/java/com/android/internal/widget/SwipeDismissLayout.java
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -35,7 +35,7 @@
public class SwipeDismissLayout extends FrameLayout {
private static final String TAG = "SwipeDismissLayout";
- private static final float DISMISS_MIN_PROGRESS = 0.6f;
+ private static final float DISMISS_MIN_DRAG_WIDTH_RATIO = .4f;
public interface OnDismissedListener {
void onDismissed(SwipeDismissLayout layout);
@@ -244,7 +244,11 @@
if (!mSwiping) {
float deltaX = ev.getRawX() - mDownX;
float deltaY = ev.getRawY() - mDownY;
- mSwiping = deltaX > mSlop * 2 && Math.abs(deltaY) < mSlop * 2;
+ if ((deltaX * deltaX) + (deltaY * deltaY) > mSlop * mSlop) {
+ mSwiping = deltaX > mSlop * 2 && Math.abs(deltaY) < mSlop * 2;
+ } else {
+ mSwiping = false;
+ }
}
}
@@ -254,12 +258,7 @@
mVelocityTracker.addMovement(ev);
mVelocityTracker.computeCurrentVelocity(1000);
- float velocityX = mVelocityTracker.getXVelocity();
- float absVelocityX = Math.abs(velocityX);
- float absVelocityY = Math.abs(mVelocityTracker.getYVelocity());
-
- if (deltaX > (getWidth() * DISMISS_MIN_PROGRESS) &&
- absVelocityX < mMinFlingVelocity &&
+ if (deltaX > (getWidth() * DISMISS_MIN_DRAG_WIDTH_RATIO) &&
ev.getRawX() >= mLastX) {
mDismissed = true;
}
@@ -267,7 +266,7 @@
// Check if the user tried to undo this.
if (mDismissed && mSwiping) {
// Check if the user's finger is actually back
- if (deltaX < (getWidth() * DISMISS_MIN_PROGRESS)) {
+ if (deltaX < (getWidth() * DISMISS_MIN_DRAG_WIDTH_RATIO)) {
mDismissed = false;
}
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 8bd2e4f..51e2871 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -241,8 +241,6 @@
# <bionic_tls.h> in com_google_android_gles_jni_GLImpl.cpp
LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
-LOCAL_LDLIBS += -lpthread -ldl
-
ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK
endif
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 08a88d1..22c17dd 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -33,6 +33,7 @@
#include "SkXfermode.h"
#include "unicode/uloc.h"
#include "unicode/ushape.h"
+#include "utils/Blur.h"
#include "TextLayout.h"
// temporary for debugging
@@ -776,19 +777,23 @@
env->ReleaseStringChars(text, textArray);
}
- static void setShadowLayer(JNIEnv* env, jobject jpaint, jfloat radius,
+ static void setShadowLayer(JNIEnv* env, jobject clazz, jlong paintHandle, jfloat radius,
jfloat dx, jfloat dy, jint color) {
- NPE_CHECK_RETURN_VOID(env, jpaint);
-
- SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
if (radius <= 0) {
paint->setLooper(NULL);
}
else {
- paint->setLooper(new SkBlurDrawLooper(radius, dx, dy, (SkColor)color))->unref();
+ SkScalar sigma = android::uirenderer::Blur::convertRadiusToSigma(radius);
+ paint->setLooper(new SkBlurDrawLooper((SkColor)color, sigma, dx, dy))->unref();
}
}
+ static jboolean hasShadowLayer(JNIEnv* env, jobject clazz, jlong paintHandle) {
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ return paint->getLooper() && paint->getLooper()->asABlurShadow(NULL);
+ }
+
static int breakText(JNIEnv* env, SkPaint& paint, const jchar text[],
int count, float maxWidth, jint bidiFlags, jfloatArray jmeasured,
SkPaint::TextBufferDirection tbd) {
@@ -968,7 +973,8 @@
(void*) SkPaintGlue::getStringBounds },
{"nativeGetCharArrayBounds", "(J[CIIILandroid/graphics/Rect;)V",
(void*) SkPaintGlue::getCharArrayBounds },
- {"nSetShadowLayer", "(FFFI)V", (void*)SkPaintGlue::setShadowLayer}
+ {"native_setShadowLayer", "(JFFFI)V", (void*)SkPaintGlue::setShadowLayer},
+ {"native_hasShadowLayer", "(J)Z", (void*)SkPaintGlue::hasShadowLayer}
};
static jfieldID req_fieldID(jfieldID id) {
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index da752752..463a0a8 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -526,12 +526,15 @@
switch (format) {
default:
- // TODO Currently the only possible values for format are AUDIO_FORMAT_PCM_16_BIT
- // and AUDIO_FORMAT_PCM_8_BIT, due to the limited set of values for audioFormat.
+ // TODO Currently the only possible values for format are AUDIO_FORMAT_PCM_16_BIT,
+ // AUDIO_FORMAT_PCM_8_BIT, and AUDIO_FORMAT_PCM_FLOAT,
+ // due to the limited set of values for audioFormat.
// The next section of the switch will probably work for more formats, but it has only
- // been tested for AUDIO_FORMAT_PCM_16_BIT, so that's why the "default" case fails.
+ // been tested for AUDIO_FORMAT_PCM_16_BIT and AUDIO_FORMAT_PCM_FLOAT,
+ // so that's why the "default" case fails.
break;
+ case AUDIO_FORMAT_PCM_FLOAT:
case AUDIO_FORMAT_PCM_16_BIT: {
// writing to shared memory, check for capacity
if ((size_t)sizeInBytes > track->sharedBuffer()->size()) {
@@ -679,6 +682,44 @@
// ----------------------------------------------------------------------------
+static jint android_media_AudioTrack_write_float(JNIEnv *env, jobject thiz,
+ jfloatArray javaAudioData,
+ jint offsetInFloats, jint sizeInFloats,
+ jint javaAudioFormat,
+ jboolean isWriteBlocking) {
+
+ sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
+ if (lpTrack == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Unable to retrieve AudioTrack pointer for write()");
+ return 0;
+ }
+
+ jfloat* cAudioData = NULL;
+ if (javaAudioData) {
+ cAudioData = (jfloat *)env->GetFloatArrayElements(javaAudioData, NULL);
+ if (cAudioData == NULL) {
+ ALOGE("Error retrieving source of audio data to play, can't play");
+ return 0; // out of memory or no data to load
+ }
+ } else {
+ ALOGE("NULL java array of audio data to play, can't play");
+ return 0;
+ }
+ jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData,
+ offsetInFloats * sizeof(float), sizeInFloats * sizeof(float),
+ isWriteBlocking == JNI_TRUE /* blocking */);
+ env->ReleaseFloatArrayElements(javaAudioData, cAudioData, 0);
+
+ if (written > 0) {
+ written /= sizeof(float);
+ }
+
+ return written;
+}
+
+
+// ----------------------------------------------------------------------------
static jint android_media_AudioTrack_get_native_frame_count(JNIEnv *env, jobject thiz) {
sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
if (lpTrack == NULL) {
@@ -963,6 +1004,7 @@
"(Ljava/lang/Object;IIIZ)I",
(void *)android_media_AudioTrack_write_native_bytes},
{"native_write_short", "([SIII)I", (void *)android_media_AudioTrack_write_short},
+ {"native_write_float", "([FIIIZ)I",(void *)android_media_AudioTrack_write_float},
{"native_setVolume", "(FF)V", (void *)android_media_AudioTrack_set_volume},
{"native_get_native_frame_count",
"()I", (void *)android_media_AudioTrack_get_native_frame_count},
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 7b2f829..fae6698 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -79,7 +79,6 @@
#define RENDERER_LOGD(...)
#endif
-#define MODIFIER_SHADOW 1
#define MODIFIER_SHADER 2
// ----------------------------------------------------------------------------
@@ -617,7 +616,6 @@
static void android_view_GLES20Canvas_resetModifiers(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint modifiers) {
OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- if (modifiers & MODIFIER_SHADOW) renderer->resetShadow();
if (modifiers & MODIFIER_SHADER) renderer->resetShader();
}
@@ -629,12 +627,6 @@
}
-static void android_view_GLES20Canvas_setupShadow(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jfloat radius, jfloat dx, jfloat dy, jint color) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- renderer->setupShadow(radius, dx, dy, color);
-}
-
// ----------------------------------------------------------------------------
// Draw filters
// ----------------------------------------------------------------------------
@@ -1032,7 +1024,6 @@
{ "nResetModifiers", "(JI)V", (void*) android_view_GLES20Canvas_resetModifiers },
{ "nSetupShader", "(JJ)V", (void*) android_view_GLES20Canvas_setupShader },
- { "nSetupShadow", "(JFFFI)V", (void*) android_view_GLES20Canvas_setupShadow },
{ "nSetupPaintFilter", "(JII)V", (void*) android_view_GLES20Canvas_setupPaintFilter },
{ "nResetPaintFilter", "(J)V", (void*) android_view_GLES20Canvas_resetPaintFilter },
diff --git a/core/res/res/drawable/btn_check_quantum_anim.xml b/core/res/res/drawable/btn_check_quantum_anim.xml
index 0600522..4b329ad 100644
--- a/core/res/res/drawable/btn_check_quantum_anim.xml
+++ b/core/res/res/drawable/btn_check_quantum_anim.xml
@@ -14,7 +14,6 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:trigger="state_checked"
android:versionCode="1" >
<size
@@ -27,53 +26,8 @@
<group>
<path
- android:name="box1"
- android:pathData="M 240,80 L 240,240 L 80,240 L 80,80 L 240,80 L 240,80 z"
- android:stroke="?attr/colorControlNormal"
- android:strokeWidth="20"
- android:strokeLineCap="round"
- android:strokeLineJoin="round" />
- </group>
- <group>
- <path
- android:name="box2"
- android:pathData="M 160,200 L 160,240 L 120,240 L 120,200 L 160,200 L 160,200 z"
- android:stroke="?attr/colorControlNormal"
- android:strokeWidth="10"
- android:strokeLineCap="round"
- android:strokeLineJoin="round" />
- </group>
- <group>
- <path
- android:name="box3"
- android:pathData="M 160,216.5 L 143.5,240 L 120,223.5 L 136.5,200 L 160,216.5 L 160,216.5 z"
- android:rotation="35"
- android:pivotX="140"
- android:pivotY="220"
- android:fill="?attr/colorControlNormal"
- android:stroke="?attr/colorControlNormal"
- android:strokeWidth="5"
- android:strokeLineCap="round"
- android:strokeLineJoin="round" />
- </group>
- <group>
- <path
- android:name="box4"
- android:pathData="M 160,216.5 L 143.5,240 L 120,223.5 L 136.5,200 L 160,216.5 L 160,216.5 z"
- android:fill="?attr/colorControlActivated"
- android:stroke="?attr/colorControlActivated"
- android:strokeLineCap="round"
- android:strokeLineJoin="round" />
- </group>
- <group>
- <path
android:name="check"
android:pathData="M 232.1,80.6 L 248.5,92.1 L 145.2,239.5 L 71.5,187.8 L 83,171.5 L 140.3,211.7 z"
android:fill="?attr/colorControlActivated" />
</group>
-
- <animation
- android:durations="300,100,0,300"
- android:sequence="box1,box2,box3,box4,check" />
-
</vector>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 4358dd3..790567e 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -31,11 +31,11 @@
<string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> uur"</string>
<string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> uur"</string>
<string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> uur"</string>
- <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> uur <xliff:g id="MINUTES">%2$d</xliff:g> minute"</string>
- <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> uur <xliff:g id="MINUTES">%2$d</xliff:g> minuut"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> u. <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> u. <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
<string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> minute"</string>
- <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> minuut <xliff:g id="SECONDS">%2$d</xliff:g> sekondes"</string>
- <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> minuut <xliff:g id="SECONDS">%2$d</xliff:g> sekond"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> s."</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> s."</string>
<string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sekondes"</string>
<string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sekonde"</string>
<string name="untitled" msgid="4638956954852782576">"<Titelloos>"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index dbc0d43..66b4a90 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -741,7 +741,7 @@
<string name="policylab_expirePassword" msgid="885279151847254056">"تنظیم زمان انقضای رمز ورود قفل صفحه"</string>
<string name="policydesc_expirePassword" msgid="1729725226314691591">"کنترل کنید چند وقت یک بار باید گذرواژه صفحه قفل عوض شود."</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"تنظیم رمزگذاری حافظه"</string>
- <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"باید اطلاعات ذخیره شده برنامه رمزگذاری شود."</string>
+ <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"اطلاعات ذخیره شده برنامه باید رمزگذاری شود."</string>
<string name="policylab_disableCamera" msgid="6395301023152297826">"غیر فعال کردن دوربین ها"</string>
<string name="policydesc_disableCamera" msgid="2306349042834754597">"جلوگیری از استفاده از همه دوربینهای دستگاه."</string>
<string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"غیرفعال کردن ویژگیها در محافظ کلید"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 03dfb12..eb2540d 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -188,10 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Suojattu tila"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string>
- <!-- no translation found for user_owner_label (2804351898001038951) -->
- <skip />
- <!-- no translation found for managed_profile_label (6260850669674791528) -->
- <skip />
+ <string name="user_owner_label" msgid="2804351898001038951">"Henkilökohtainen"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Työ"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Maksulliset palvelut"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Suorita mahdollisesti maksullisia toimintoja."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Omat viestit"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index ea9ffb3..751327b 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -188,10 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Mod selamat"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
- <!-- no translation found for user_owner_label (2804351898001038951) -->
- <skip />
- <!-- no translation found for managed_profile_label (6260850669674791528) -->
- <skip />
+ <string name="user_owner_label" msgid="2804351898001038951">"Peribadi"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Tempat Kerja"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Perkhidmatan yang anda perlu bayar"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Melakukan perkara yang boleh mengenakan bayaran kepada anda."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Mesej anda"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index ecec099..f9b9fd2 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -31,13 +31,13 @@
<string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dia <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
<string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dia <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
<string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> horas"</string>
- <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
- <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
- <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min."</string>
- <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> seg."</string>
- <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> seg."</string>
- <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> seg."</string>
- <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> seg."</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> seg"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> seg"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> seg"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> seg"</string>
<string name="untitled" msgid="4638956954852782576">"<Sem nome>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 93107ca..be2ed29 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -188,10 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">">999"</string>
<string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <!-- no translation found for user_owner_label (2804351898001038951) -->
- <skip />
- <!-- no translation found for managed_profile_label (6260850669674791528) -->
- <skip />
+ <string name="user_owner_label" msgid="2804351898001038951">"Pessoal"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Trabalho"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serviços que geram gastos"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Faça coisas que podem custar dinheiro."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Suas mensagens"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 568e093..33a5a81 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -188,10 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"˃999"</string>
<string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistemul Android"</string>
- <!-- no translation found for user_owner_label (2804351898001038951) -->
- <skip />
- <!-- no translation found for managed_profile_label (6260850669674791528) -->
- <skip />
+ <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Serviciu"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicii cu plată"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Efectuează acţiuni care sunt cu plată."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Mesajele dvs."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 8a0141a..c7c5a08 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -34,10 +34,10 @@
<string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ч. <xliff:g id="MINUTES">%2$d</xliff:g> мин."</string>
<string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ч. <xliff:g id="MINUTES">%2$d</xliff:g> мин."</string>
<string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> мин."</string>
- <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> мин. <xliff:g id="SECONDS">%2$d</xliff:g> с."</string>
- <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> мин. <xliff:g id="SECONDS">%2$d</xliff:g> с."</string>
- <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> с."</string>
- <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> с."</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> мин. <xliff:g id="SECONDS">%2$d</xliff:g> с"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> мин. <xliff:g id="SECONDS">%2$d</xliff:g> с"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> с"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> с"</string>
<string name="untitled" msgid="4638956954852782576">"<Без названия>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"..."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 793e5bf..3476692 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -188,10 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
- <!-- no translation found for user_owner_label (2804351898001038951) -->
- <skip />
- <!-- no translation found for managed_profile_label (6260850669674791528) -->
- <skip />
+ <string name="user_owner_label" msgid="2804351898001038951">"个人"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"企业"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"需要您付费的服务"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"执行可能需要您付费的操作。"</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"您的信息"</string>
@@ -716,8 +714,8 @@
<string name="permdesc_accessNotifications" msgid="458457742683431387">"允许该应用检索、检查并清除通知,包括其他应用发布的通知。"</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"绑定到通知侦听器服务"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"允许应用绑定到通知侦听器服务的顶级接口(普通应用绝不需要此权限)。"</string>
- <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"绑定到条件提供方服务"</string>
- <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"允许应用绑定到条件提供方服务的顶级接口。普通应用绝不需要此权限。"</string>
+ <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"绑定到条件提供程序服务"</string>
+ <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"允许应用绑定到条件提供程序服务的顶级接口。普通应用绝不需要此权限。"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"调用运营商提供的配置应用"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"允许应用调用运营商提供的配置应用。普通应用绝不需要此权限。"</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"监听网络状况的观测信息"</string>
@@ -1388,7 +1386,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"壁纸"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"更改壁纸"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"通知侦听器"</string>
- <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"条件提供方"</string>
+ <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"条件提供程序"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN 已激活"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"“<xliff:g id="APP">%s</xliff:g>”已激活 VPN"</string>
<string name="vpn_text" msgid="3011306607126450322">"触摸可管理网络。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 547ca27..4a67538 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1169,7 +1169,7 @@
<string name="whichHomeApplication" msgid="4616420172727326782">"選取主螢幕應用程式"</string>
<string name="alwaysUse" msgid="4583018368000610438">"設為預設應用程式。"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"前往 [系統設定] > [應用程式] > [下載] 清除預設值。"</string>
- <string name="chooseActivity" msgid="7486876147751803333">"選擇一種動作"</string>
+ <string name="chooseActivity" msgid="7486876147751803333">"選擇分享方式"</string>
<string name="chooseUsbActivity" msgid="6894748416073583509">"選取要以 USB 裝置存取的應用程式"</string>
<string name="noApplications" msgid="2991814273936504689">"沒有應用程式可執行這項操作。"</string>
<string name="aerr_title" msgid="1905800560317137752"></string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 172877f..d9473ec 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4660,18 +4660,6 @@
<!-- Drawable used to draw Vector Drawables. -->
<declare-styleable name="VectorDrawable">
- <!-- What event triggers the animation -->
- <attr name="trigger" format="enum">
- <enum name="state_pressed" value="1" />
- <enum name="state_focused" value="2" />
- <enum name="state_hovered" value="3" />
- <enum name="state_selected" value="4" />
- <enum name="state_checkable" value="5" />
- <enum name="state_checked" value="6" />
- <enum name="state_enabled" value="7" />
- <enum name="state_activated" value="8" />
- <enum name="state_window_focused" value="9" />
- </attr>
<attr name="versionCode" />
</declare-styleable>
@@ -4691,42 +4679,6 @@
<attr name="height" />
</declare-styleable>
- <!-- Define the animations of drawable -->
- <declare-styleable name="VectorDrawableAnimation">
- <!-- Configures this animation sequence between the named paths -->
- <attr name="sequence" format="string"/>
- <!-- Limits an animation to only interpolate the selected variable -->
- <attr name="limitTo" format="enum">
- <enum name="unlimited" value="0"/>
- <enum name="path" value="1"/>
- <enum name="rotation" value="2"/>
- <enum name="trimPathStart" value="3"/>
- <enum name="trimPathEnd" value="4"/>
- <enum name="trimPathOffset" value="5"/>
- </attr>
- <!-- Number of times to loop this aspect of the animation -->
- <attr name="repeatCount"/>
- <!-- A list of times in milliseconds to transision from on path to another.
- List must contain one less than the number of named paths
- e.g. given sequence="A,B,C,D" durations="100,0,100" implies 100ms for the
- "A" to "B" transision instantanious switch to "C" and 100ms for "C" to "D". -->
- <attr name="durations" format="string" />
- <!-- The delay before stating this aspect of the animation in milli seconds -->
- <attr name="startDelay" />
- <!-- when repeating how does it repeat back and forth or a to b -->
- <attr name="repeatStyle" format="enum">
- <enum name="forward" value="0"/>
- <enum name="reverse" value="1"/>[]
- </attr>
- <!-- how does the animation progress from start to finish -->
- <attr name="animate" format="enum">
- <enum name="linear" value="0"/>
- <enum name="easeIn" value="1"/>
- <enum name="easeOut" value="2"/>
- <enum name="easeInOut" value="3"/>
- </attr>
- </declare-styleable>
-
<!-- Defines the path used in Vector Drawables. -->
<declare-styleable name="VectorDrawablePath">
<!-- The Name of this path -->
@@ -4771,26 +4723,6 @@
</attr>
<!-- sets the Miter limit for a stroked path -->
<attr name="strokeMiterLimit" format="float"/>
- <!-- sets a condition to be met to draw path -->
- <attr name="state_pressed" />
- <!-- sets a condition to be met to draw path -->
- <attr name="state_focused" />
- <!-- sets a condition to be met to draw path -->
- <attr name="state_selected" />
- <!-- sets a condition to be met to draw path -->
- <attr name="state_window_focused" />
- <!-- sets a condition to be met to draw path -->
- <attr name="state_enabled" />
- <!-- sets a condition to be met to draw path -->
- <attr name="state_activated" />
- <!-- sets a condition to be met to draw path -->
- <attr name="state_accelerated" />
- <!-- sets a condition to be met to draw path -->
- <attr name="state_hovered" />
- <!-- sets a condition to be met to draw path -->
- <attr name="state_checked" />
- <!-- sets a condition to be met to draw path -->
- <attr name="state_checkable" />
</declare-styleable>
<!-- ========================== -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index d0cdefe..4e584c0 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2116,7 +2116,6 @@
<public type="attr" name="controlY2" />
<public type="attr" name="sharedElementName" />
<public type="attr" name="transitionGroup" />
- <public type="attr" name="trigger" />
<public type="attr" name="viewportWidth" />
<public type="attr" name="viewportHeight" />
<public type="attr" name="fillOpacity" />
@@ -2125,17 +2124,12 @@
<public type="attr" name="stroke" />
<public type="attr" name="strokeOpacity" />
<public type="attr" name="strokeWidth" />
- <public type="attr" name="durations" />
- <public type="attr" name="sequence" />
- <public type="attr" name="repeatStyle" />
<public type="attr" name="trimPathStart" />
<public type="attr" name="trimPathEnd" />
<public type="attr" name="trimPathOffset" />
<public type="attr" name="strokeLineCap" />
<public type="attr" name="strokeLineJoin" />
<public type="attr" name="clipToPath" />
- <public type="attr" name="animate" />
- <public type="attr" name="limitTo" />
<public type="attr" name="requiredForProfile"/>
<public type="attr" name="pinned" />
<public type="attr" name="colorControlNormal" />
diff --git a/core/tests/inputmethodtests/run_core_inputmethod_test.sh b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
index 9029ba5..e0f4f6d 100755
--- a/core/tests/inputmethodtests/run_core_inputmethod_test.sh
+++ b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
@@ -21,4 +21,4 @@
$COMMAND
fi
-adb shell am instrument -w -e class android.os.InputMethodTest,android.os.InputMethodSubtypeArrayTest,android.os.InputMethodSubtypeSwitchingControllerTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner
+adb shell am instrument -w -e class android.os.InputMethodTest,android.os.InputMethodSubtypeArrayTest,android.os.InputMethodSubtypeSwitchingControllerTest,android.os.CursorAnchorInfoTest,android.os.SparseRectFArrayTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner
diff --git a/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java b/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java
new file mode 100644
index 0000000..59a6314
--- /dev/null
+++ b/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.graphics.Matrix;
+import android.graphics.RectF;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.CursorAnchorInfo;
+import android.view.inputmethod.CursorAnchorInfo.CursorAnchorInfoBuilder;
+
+public class CursorAnchorInfoTest extends InstrumentationTestCase {
+ // null represents a character that is invisible, for example because it's overlapped by some
+ // other UI elements.
+ private static final RectF[] MANY_RECTS = new RectF[] {
+ null,
+ new RectF(102.0f, 202.0f, 302.0f, 402.0f),
+ new RectF(103.0f, 203.0f, 303.0f, 403.0f),
+ new RectF(104.0f, 204.0f, 304.0f, 404.0f),
+ new RectF(105.0f, 205.0f, 305.0f, 405.0f),
+ new RectF(106.0f, 206.0f, 306.0f, 406.0f),
+ null,
+ new RectF(108.0f, 208.0f, 308.0f, 408.0f),
+ new RectF(109.0f, 209.0f, 309.0f, 409.0f),
+ new RectF(110.0f, 210.0f, 310.0f, 410.0f),
+ new RectF(111.0f, 211.0f, 311.0f, 411.0f),
+ new RectF(112.0f, 212.0f, 312.0f, 412.0f),
+ new RectF(113.0f, 213.0f, 313.0f, 413.0f),
+ new RectF(114.0f, 214.0f, 314.0f, 414.0f),
+ new RectF(115.0f, 215.0f, 315.0f, 415.0f),
+ new RectF(116.0f, 216.0f, 316.0f, 416.0f),
+ new RectF(117.0f, 217.0f, 317.0f, 417.0f),
+ null,
+ null,
+ };
+
+ @SmallTest
+ public void testBuilder() throws Exception {
+ final int SELECTION_START = 30;
+ final int SELECTION_END = 40;
+ final int CANDIDATES_START = 32;
+ final int CANDIDATES_END = 33;
+ final float INSERTION_MARKER_HORIZONTAL = 10.5f;
+ final float INSERTION_MARKER_TOP = 100.1f;
+ final float INSERTION_MARKER_BASELINE = 110.4f;
+ final float INSERTION_MARKER_BOTOM = 111.0f;
+ Matrix TRANSFORM_MATRIX = new Matrix(Matrix.IDENTITY_MATRIX);
+ TRANSFORM_MATRIX.setScale(10.0f, 20.0f);
+
+ final CursorAnchorInfoBuilder builder = new CursorAnchorInfoBuilder();
+ builder.setSelectionRange(SELECTION_START, SELECTION_END)
+ .setCandidateRange(CANDIDATES_START, CANDIDATES_END)
+ .setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP,
+ INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM)
+ .setMatrix(TRANSFORM_MATRIX);
+ for (int i = 0; i < MANY_RECTS.length; i++) {
+ final RectF rect = MANY_RECTS[i];
+ if (rect != null) {
+ builder.addCharacterRect(i, rect.left, rect.top, rect.right, rect.bottom);
+ }
+ }
+
+ final CursorAnchorInfo info = builder.build();
+ assertEquals(SELECTION_START, info.getSelectionStart());
+ assertEquals(SELECTION_END, info.getSelectionEnd());
+ assertEquals(CANDIDATES_START, info.getCandidatesStart());
+ assertEquals(CANDIDATES_END, info.getCandidatesEnd());
+ assertEquals(INSERTION_MARKER_HORIZONTAL, info.getInsertionMarkerHorizontal());
+ assertEquals(INSERTION_MARKER_TOP, info.getInsertionMarkerTop());
+ assertEquals(INSERTION_MARKER_BASELINE, info.getInsertionMarkerBaseline());
+ assertEquals(INSERTION_MARKER_BOTOM, info.getInsertionMarkerBottom());
+ assertEquals(TRANSFORM_MATRIX, info.getMatrix());
+ for (int i = 0; i < MANY_RECTS.length; i++) {
+ final RectF rect = MANY_RECTS[i];
+ assertEquals(rect, info.getCharacterRect(i));
+ }
+
+ // Make sure that the builder can reproduce the same object.
+ final CursorAnchorInfo info2 = builder.build();
+ assertEquals(SELECTION_START, info2.getSelectionStart());
+ assertEquals(SELECTION_END, info2.getSelectionEnd());
+ assertEquals(CANDIDATES_START, info2.getCandidatesStart());
+ assertEquals(CANDIDATES_END, info2.getCandidatesEnd());
+ assertEquals(INSERTION_MARKER_HORIZONTAL, info2.getInsertionMarkerHorizontal());
+ assertEquals(INSERTION_MARKER_TOP, info2.getInsertionMarkerTop());
+ assertEquals(INSERTION_MARKER_BASELINE, info2.getInsertionMarkerBaseline());
+ assertEquals(INSERTION_MARKER_BOTOM, info2.getInsertionMarkerBottom());
+ assertEquals(TRANSFORM_MATRIX, info2.getMatrix());
+ for (int i = 0; i < MANY_RECTS.length; i++) {
+ final RectF rect = MANY_RECTS[i];
+ assertEquals(rect, info2.getCharacterRect(i));
+ }
+ assertEquals(info, info2);
+ assertEquals(info.hashCode(), info2.hashCode());
+
+ // Make sure that object can be marshalled via {@link Parsel}.
+ final CursorAnchorInfo info3 = cloneViaParcel(info2);
+ assertEquals(SELECTION_START, info3.getSelectionStart());
+ assertEquals(SELECTION_END, info3.getSelectionEnd());
+ assertEquals(CANDIDATES_START, info3.getCandidatesStart());
+ assertEquals(CANDIDATES_END, info3.getCandidatesEnd());
+ assertEquals(INSERTION_MARKER_HORIZONTAL, info3.getInsertionMarkerHorizontal());
+ assertEquals(INSERTION_MARKER_TOP, info3.getInsertionMarkerTop());
+ assertEquals(INSERTION_MARKER_BASELINE, info3.getInsertionMarkerBaseline());
+ assertEquals(INSERTION_MARKER_BOTOM, info3.getInsertionMarkerBottom());
+ assertEquals(TRANSFORM_MATRIX, info3.getMatrix());
+ for (int i = 0; i < MANY_RECTS.length; i++) {
+ final RectF rect = MANY_RECTS[i];
+ assertEquals(rect, info3.getCharacterRect(i));
+ }
+ assertEquals(info.hashCode(), info3.hashCode());
+
+ builder.reset();
+ final CursorAnchorInfo uninitializedInfo = builder.build();
+ assertEquals(-1, uninitializedInfo.getSelectionStart());
+ assertEquals(-1, uninitializedInfo.getSelectionEnd());
+ assertEquals(-1, uninitializedInfo.getCandidatesStart());
+ assertEquals(-1, uninitializedInfo.getCandidatesEnd());
+ assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerHorizontal());
+ assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerTop());
+ assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBaseline());
+ assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBottom());
+ assertEquals(Matrix.IDENTITY_MATRIX, uninitializedInfo.getMatrix());
+ }
+
+ @SmallTest
+ public void testBuilderAdd() throws Exception {
+ // A negative index should be rejected.
+ try {
+ new CursorAnchorInfoBuilder().addCharacterRect(-1, 0.0f, 0.0f, 0.0f, 0.0f);
+ } catch (IllegalArgumentException ex) {
+ assertTrue(true);
+ }
+ }
+
+ private static CursorAnchorInfo cloneViaParcel(final CursorAnchorInfo src) {
+ Parcel parcel = null;
+ try {
+ parcel = Parcel.obtain();
+ src.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ return new CursorAnchorInfo(parcel);
+ } finally {
+ if (parcel != null) {
+ parcel.recycle();
+ }
+ }
+ }
+}
+
diff --git a/core/tests/inputmethodtests/src/android/os/SparseRectFArrayTest.java b/core/tests/inputmethodtests/src/android/os/SparseRectFArrayTest.java
new file mode 100644
index 0000000..fae7230
--- /dev/null
+++ b/core/tests/inputmethodtests/src/android/os/SparseRectFArrayTest.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.graphics.RectF;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.SparseRectFArray;
+import android.view.inputmethod.SparseRectFArray.SparseRectFArrayBuilder;
+
+import java.util.Objects;
+
+public class SparseRectFArrayTest extends InstrumentationTestCase {
+ // A test data for {@link SparseRectFArray}. null represents the gap of indices.
+ private static final RectF[] MANY_RECTS = new RectF[] {
+ null,
+ new RectF(102.0f, 202.0f, 302.0f, 402.0f),
+ new RectF(103.0f, 203.0f, 303.0f, 403.0f),
+ new RectF(104.0f, 204.0f, 304.0f, 404.0f),
+ new RectF(105.0f, 205.0f, 305.0f, 405.0f),
+ new RectF(106.0f, 206.0f, 306.0f, 406.0f),
+ null,
+ new RectF(108.0f, 208.0f, 308.0f, 408.0f),
+ new RectF(109.0f, 209.0f, 309.0f, 409.0f),
+ new RectF(110.0f, 210.0f, 310.0f, 410.0f),
+ new RectF(111.0f, 211.0f, 311.0f, 411.0f),
+ new RectF(112.0f, 212.0f, 312.0f, 412.0f),
+ new RectF(113.0f, 213.0f, 313.0f, 413.0f),
+ new RectF(114.0f, 214.0f, 314.0f, 414.0f),
+ new RectF(115.0f, 215.0f, 315.0f, 415.0f),
+ new RectF(116.0f, 216.0f, 316.0f, 416.0f),
+ new RectF(117.0f, 217.0f, 317.0f, 417.0f),
+ null,
+ null,
+ new RectF(118.0f, 218.0f, 318.0f, 418.0f),
+ };
+
+ @SmallTest
+ public void testBuilder() throws Exception {
+ final RectF TEMP_RECT = new RectF(10.0f, 20.0f, 30.0f, 40.0f);
+
+ final SparseRectFArrayBuilder builder = new SparseRectFArrayBuilder();
+ builder.append(100, TEMP_RECT.left, TEMP_RECT.top, TEMP_RECT.right, TEMP_RECT.bottom);
+ assertNull(builder.build().get(-1));
+ assertNull(builder.build().get(0));
+ assertNull(builder.build().get(99));
+ assertEquals(TEMP_RECT, builder.build().get(100));
+ assertNull(builder.build().get(101));
+
+ // Test if {@link SparseRectFArrayBuilder#reset} resets its internal state.
+ builder.reset();
+ assertNull(builder.build().get(100));
+
+ builder.reset();
+ for (int i = 0; i < MANY_RECTS.length; i++) {
+ final RectF rect = MANY_RECTS[i];
+ if (rect != null) {
+ builder.append(i, rect.left, rect.top, rect.right, rect.bottom);
+ }
+ }
+ final SparseRectFArray array = builder.build();
+ for (int i = 0; i < MANY_RECTS.length; i++) {
+ final RectF rect = MANY_RECTS[i];
+ assertEquals(rect, array.get(i));
+ }
+
+ // Make sure the builder reproduces an equivalent object.
+ final SparseRectFArray array2 = builder.build();
+ for (int i = 0; i < MANY_RECTS.length; i++) {
+ final RectF rect = MANY_RECTS[i];
+ assertEquals(rect, array2.get(i));
+ }
+ assertEqualRects(array, array2);
+
+ // Make sure the instance can be marshaled via {@link Parcel}.
+ final SparseRectFArray array3 = cloneViaParcel(array);
+ for (int i = 0; i < MANY_RECTS.length; i++) {
+ final RectF rect = MANY_RECTS[i];
+ assertEquals(rect, array3.get(i));
+ }
+ assertEqualRects(array, array3);
+
+ // Make sure the builder can be reset.
+ builder.reset();
+ assertNull(builder.build().get(0));
+ }
+
+ @SmallTest
+ public void testEquality() throws Exception {
+ // Empty array should be equal.
+ assertEqualRects(new SparseRectFArrayBuilder().build(),
+ new SparseRectFArrayBuilder().build());
+
+ assertEqualRects(
+ new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f).build(),
+ new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f).build());
+ assertNotEqualRects(
+ new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f).build(),
+ new SparseRectFArrayBuilder().append(100, 2.0f, 2.0f, 3.0f, 4.0f).build());
+ assertNotEqualRects(
+ new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f).build(),
+ new SparseRectFArrayBuilder().append(101, 1.0f, 2.0f, 3.0f, 4.0f).build());
+
+ assertEqualRects(
+ new SparseRectFArrayBuilder()
+ .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+ .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build(),
+ new SparseRectFArrayBuilder()
+ .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+ .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build());
+ assertNotEqualRects(
+ new SparseRectFArrayBuilder()
+ .append(100, 1.0f, 2.0f, 3.0f, 4.0f).build(),
+ new SparseRectFArrayBuilder()
+ .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+ .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build());
+ assertNotEqualRects(
+ new SparseRectFArrayBuilder()
+ .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+ .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build(),
+ new SparseRectFArrayBuilder()
+ .append(100, 1.0f, 2.0f, 3.0f, 4.0f).build());
+ assertNotEqualRects(
+ new SparseRectFArrayBuilder()
+ .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+ .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build(),
+ new SparseRectFArrayBuilder()
+ .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+ .append(101, 1.0f, 0.0f, 0.0f, 0.0f).build());
+ assertNotEqualRects(
+ new SparseRectFArrayBuilder()
+ .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+ .append(101, 1.0f, 0.0f, 0.0f, 0.0f).build(),
+ new SparseRectFArrayBuilder()
+ .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+ .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build());
+ assertNotEqualRects(
+ new SparseRectFArrayBuilder()
+ .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+ .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build(),
+ new SparseRectFArrayBuilder()
+ .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+ .append(102, 0.0f, 0.0f, 0.0f, 0.0f).build());
+
+ assertEqualRects(
+ new SparseRectFArrayBuilder()
+ .append(1, 1.0f, 2.0f, 3.0f, 4.0f)
+ .append(1000, 0.0f, 0.0f, 0.0f, 0.0f)
+ .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f)
+ .build(),
+ new SparseRectFArrayBuilder()
+ .append(1, 1.0f, 2.0f, 3.0f, 4.0f)
+ .append(1000, 0.0f, 0.0f, 0.0f, 0.0f)
+ .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f)
+ .build());
+
+ assertNotEqualRects(
+ new SparseRectFArrayBuilder()
+ .append(1, 1.0f, 2.0f, 3.0f, 4.0f)
+ .append(1000, 0.0f, 0.0f, 0.0f, 0.0f)
+ .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f)
+ .build(),
+ new SparseRectFArrayBuilder()
+ .append(1, 1.0f, 2.0f, 3.0f, 4.0f)
+ .build());
+ assertNotEqualRects(
+ new SparseRectFArrayBuilder()
+ .append(1, 1.0f, 2.0f, 3.0f, 4.0f)
+ .append(1000, 0.0f, 0.0f, 0.0f, 0.0f)
+ .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f)
+ .build(),
+ new SparseRectFArrayBuilder()
+ .append(1, 1.0f, 2.0f, 3.0f, 4.0f)
+ .append(1000, 1.0f, 0.0f, 0.0f, 0.0f)
+ .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f)
+ .build());
+ }
+
+ @SmallTest
+ public void testBuilderAppend() throws Exception {
+ // Key should be appended in ascending order.
+ try {
+ new SparseRectFArrayBuilder().append(10, 0, 0, 0, 0).append(0, 1, 2, 3, 4);
+ } catch (IllegalArgumentException ex) {
+ assertTrue(true);
+ }
+
+ try {
+ new SparseRectFArrayBuilder().append(10, 0, 0, 0, 0).append(10, 1, 2, 3, 4);
+ } catch (IllegalArgumentException ex) {
+ assertTrue(true);
+ }
+ }
+
+ private static void assertEqualRects(SparseRectFArray a, SparseRectFArray b) {
+ assertEquals(a, b);
+ if (a != null && b != null) {
+ assertEquals(a.hashCode(), b.hashCode());
+ }
+ }
+
+ private static void assertNotEqualRects(SparseRectFArray a, SparseRectFArray b) {
+ assertFalse(Objects.equals(a, b));
+ }
+
+ private static SparseRectFArray cloneViaParcel(final SparseRectFArray src) {
+ Parcel parcel = null;
+ try {
+ parcel = Parcel.obtain();
+ src.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ return new SparseRectFArray(parcel);
+ } finally {
+ if (parcel != null) {
+ parcel.recycle();
+ }
+ }
+ }
+}
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
index 4057736..6143b4b 100644
--- a/docs/html/guide/topics/manifest/uses-feature-element.jd
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -584,9 +584,14 @@
</tr>
<tr>
<td><code>android.hardware.camera.any</code></td>
- <td>The application uses at least one camera facing in any direction. Use this
-in preference to <code>android.hardware.camera</code> if a back-facing camera is
-not required.</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>
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 1e1128e..457b3ea 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -55,27 +55,6 @@
/**
* @hide
*/
- public boolean hasShadow;
- /**
- * @hide
- */
- public float shadowDx;
- /**
- * @hide
- */
- public float shadowDy;
- /**
- * @hide
- */
- public float shadowRadius;
- /**
- * @hide
- */
- public int shadowColor;
-
- /**
- * @hide
- */
public int mBidiFlags = BIDI_DEFAULT_LTR;
static final Style[] sStyleArray = {
@@ -492,12 +471,6 @@
mCompatScaling = 1;
mInvCompatScaling = 1;
- hasShadow = false;
- shadowDx = 0;
- shadowDy = 0;
- shadowRadius = 0;
- shadowColor = 0;
-
mBidiFlags = BIDI_DEFAULT_LTR;
setTextLocale(Locale.getDefault());
setElegantTextHeight(false);
@@ -538,12 +511,6 @@
mCompatScaling = paint.mCompatScaling;
mInvCompatScaling = paint.mInvCompatScaling;
- hasShadow = paint.hasShadow;
- shadowDx = paint.shadowDx;
- shadowDy = paint.shadowDy;
- shadowRadius = paint.shadowRadius;
- shadowColor = paint.shadowColor;
-
mBidiFlags = paint.mBidiFlags;
mLocale = paint.mLocale;
}
@@ -1135,22 +1102,24 @@
* layer is removed.
*/
public void setShadowLayer(float radius, float dx, float dy, int color) {
- hasShadow = radius > 0.0f;
- shadowRadius = radius;
- shadowDx = dx;
- shadowDy = dy;
- shadowColor = color;
- nSetShadowLayer(radius, dx, dy, color);
+ native_setShadowLayer(mNativePaint, radius, dx, dy, color);
}
-
- private native void nSetShadowLayer(float radius, float dx, float dy, int color);
/**
* Clear the shadow layer.
*/
public void clearShadowLayer() {
- hasShadow = false;
- nSetShadowLayer(0, 0, 0, 0);
+ setShadowLayer(0, 0, 0, 0);
+ }
+
+ /**
+ * Checks if the paint has a shadow layer attached
+ *
+ * @return true if the paint has a shadow layer attached and false otherwise
+ * @hide
+ */
+ public boolean hasShadowLayer() {
+ return native_hasShadowLayer(mNativePaint);
}
/**
@@ -2295,4 +2264,8 @@
private static native void nativeGetCharArrayBounds(long nativePaint,
char[] text, int index, int count, int bidiFlags, Rect bounds);
private static native void finalizer(long nativePaint);
+
+ private static native void native_setShadowLayer(long native_object,
+ float radius, float dx, float dy, int color);
+ private static native boolean native_hasShadowLayer(long native_object);
}
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 3f8c45c..0862cdd 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -18,6 +18,7 @@
import java.lang.ref.WeakReference;
+import android.annotation.Nullable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -132,14 +133,14 @@
* Register a callback to be invoked when a new image frame becomes available to the
* SurfaceTexture.
* <p>
- * This callback may be called on an arbitrary thread, so it is not
+ * The callback may be called on an arbitrary thread, so it is not
* safe to call {@link #updateTexImage} without first binding the OpenGL ES context to the
* thread invoking the callback.
* </p>
*
- * @param listener The listener to set.
+ * @param listener The listener to use, or null to remove the listener.
*/
- public void setOnFrameAvailableListener(OnFrameAvailableListener listener) {
+ public void setOnFrameAvailableListener(@Nullable OnFrameAvailableListener listener) {
setOnFrameAvailableListener(listener, null);
}
@@ -147,17 +148,18 @@
* Register a callback to be invoked when a new image frame becomes available to the
* SurfaceTexture.
* <p>
- * If no handler is specified, then this callback may be called on an arbitrary thread,
+ * If a handler is specified, the callback will be invoked on that handler's thread.
+ * If no handler is specified, then the callback may be called on an arbitrary thread,
* so it is not safe to call {@link #updateTexImage} without first binding the OpenGL ES
* context to the thread invoking the callback.
* </p>
*
- * @param listener The listener to set.
+ * @param listener The listener to use, or null to remove the listener.
* @param handler The handler on which the listener should be invoked, or null
* to use an arbitrary thread.
*/
- public void setOnFrameAvailableListener(final OnFrameAvailableListener listener,
- Handler handler) {
+ public void setOnFrameAvailableListener(@Nullable final OnFrameAvailableListener listener,
+ @Nullable Handler handler) {
if (listener != null) {
// Although we claim the thread is arbitrary, earlier implementation would
// prefer to send the callback on the creating looper or the main looper
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 61b1b85..99ab4dd 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -237,7 +237,7 @@
paint.setAlpha(modulateAlpha(prevAlpha, state.mAlpha));
// only draw shape if it may affect output
- if (paint.getAlpha() != 0 || paint.getXfermode() != null || paint.hasShadow) {
+ if (paint.getAlpha() != 0 || paint.getXfermode() != null || paint.hasShadowLayer()) {
final boolean clearColorFilter;
if (mTintFilter != null && paint.getColorFilter() == null) {
paint.setColorFilter(mTintFilter);
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 77712b6..ff4ab98 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -14,8 +14,6 @@
package android.graphics.drawable;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
@@ -31,9 +29,6 @@
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
import com.android.internal.R;
@@ -46,7 +41,6 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
-import java.util.HashSet;
/**
* This lets you create a drawable based on an XML vector graphic It can be
@@ -56,8 +50,6 @@
* <p/>
* <dl>
* <dt><code><vector></code></dt>
- * <dd>The attribute <code>android:trigger</code> defines a state change that
- * will drive the animation</dd>
* <dd>The attribute <code>android:versionCode</code> defines the version of
* VectorDrawable</dd>
* <dt><code><size></code></dt>
@@ -68,8 +60,7 @@
* The size is defined using the attributes <code>android:viewportHeight</code>
* <code>android:viewportWidth</code></dd>
* <dt><code><group></code></dt>
- * <dd>Defines a "key frame" in the animation if there is only one group the
- * drawable is static 2D image that has no animation.</dd>
+ * <dd>Defines the static 2D image.</dd>
* <dt><code><path></code></dt>
* <dd>Defines paths to be drawn. The path elements must be within a group
* <dl>
@@ -109,48 +100,6 @@
* <dd>Sets the lineJoin for a stroked path: miter,round,bevel</dd></dt>
* <dt><code>android:strokeMiterLimit</code>
* <dd>Sets the Miter limit for a stroked path</dd></dt>
- * <dt><code>android:state_pressed</code>
- * <dd>Sets a condition to be met to draw path</dd></dt>
- * <dt><code>android:state_focused</code>
- * <dd>Sets a condition to be met to draw path</dd></dt>
- * <dt><code>android:state_selected</code>
- * <dd>Sets a condition to be met to draw path</dd></dt>
- * <dt><code>android:state_window_focused</code>
- * <dd>Sets a condition to be met to draw path</dd></dt>
- * <dt><code>android:state_enabled</code>
- * <dd>Sets a condition to be met to draw path</dd></dt>
- * <dt><code>android:state_activated</code>
- * <dd>Sets a condition to be met to draw path</dd></dt>
- * <dt><code>android:state_accelerated</code>
- * <dd>Sets a condition to be met to draw path</dd></dt>
- * <dt><code>android:state_hovered</code>
- * <dd>Sets a condition to be met to draw path</dd></dt>
- * <dt><code>android:state_checked</code>
- * <dd>Sets a condition to be met to draw path</dd></dt>
- * <dt><code>android:state_checkable</code>
- * <dd>Sets a condition to be met to draw path</dd></dt>
- * </dl>
- * </dd>
- * <dt><code><animation></code></dt>
- * <dd>Used to customize the transition between two paths
- * <dl>
- * <dt><code>android:sequence</code>
- * <dd>Configures this animation sequence between the named paths.</dd></dt>
- * <dt><code>android:limitTo</code>
- * <dd>Limits an animation to only interpolate the selected variable unlimited,
- * path, rotation, trimPathStart, trimPathEnd, trimPathOffset</dd></dt>
- * <dt><code>android:repeatCount</code>
- * <dd>Number of times to loop this aspect of the animation</dd></dt>
- * <dt><code>android:durations</code>
- * <dd>The duration of each step in the animation in milliseconds Must contain
- * the number of named paths - 1</dd></dt>
- * <dt><code>android:startDelay</code>
- * <dd></dd></dt>
- * <dt><code>android:repeatStyle</code>
- * <dd>when repeating how does it repeat back and forth or a to b: forward,
- * inAndOut</dd></dt>
- * <dt><code>android:animate</code>
- * <dd>linear, accelerate, decelerate, easing</dd></dt>
* </dl>
* </dd>
*/
@@ -161,8 +110,6 @@
private static final String SHAPE_VIEWPORT = "viewport";
private static final String SHAPE_GROUP = "group";
private static final String SHAPE_PATH = "path";
- private static final String SHAPE_TRANSITION = "transition";
- private static final String SHAPE_ANIMATION = "animation";
private static final String SHAPE_VECTOR = "vector";
private static final int LINECAP_BUTT = 0;
@@ -173,9 +120,6 @@
private static final int LINEJOIN_ROUND = 1;
private static final int LINEJOIN_BEVEL = 2;
- private static final int DEFAULT_DURATION = 1000;
- private static final long DEFAULT_INFINITE_DURATION = 60 * 60 * 1000;
-
private final VectorDrawableState mVectorState;
private int mAlpha = 0xFF;
@@ -202,7 +146,7 @@
final int saveCount = canvas.save();
final Rect bounds = getBounds();
canvas.translate(bounds.left, bounds.top);
- mVectorState.mVAnimatedPath.draw(canvas, bounds.width(), bounds.height());
+ mVectorState.mVPathRenderer.draw(canvas, bounds.width(), bounds.height());
canvas.restoreToCount(saveCount);
}
@@ -255,12 +199,12 @@
@Override
public int getIntrinsicWidth() {
- return (int) mVectorState.mVAnimatedPath.mBaseWidth;
+ return (int) mVectorState.mVPathRenderer.mBaseWidth;
}
@Override
public int getIntrinsicHeight() {
- return (int) mVectorState.mVAnimatedPath.mBaseHeight;
+ return (int) mVectorState.mVPathRenderer.mBaseHeight;
}
@Override
@@ -276,8 +220,8 @@
@Override
public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
- final VAnimatedPath p = inflateInternal(res, parser, attrs, theme);
- setAnimatedPath(p);
+ final VPathRenderer p = inflateInternal(res, parser, attrs, theme);
+ setPathRenderer(p);
}
@Override
@@ -290,7 +234,7 @@
super.applyTheme(t);
final VectorDrawableState state = mVectorState;
- final VAnimatedPath path = state.mVAnimatedPath;
+ final VPathRenderer path = state.mVPathRenderer;
if (path != null && path.canApplyTheme()) {
path.applyTheme(t);
}
@@ -316,9 +260,9 @@
return null;
}
- private VAnimatedPath inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
+ private VPathRenderer inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
Theme theme) throws XmlPullParserException, IOException {
- final VAnimatedPath animatedPath = new VAnimatedPath();
+ final VPathRenderer pathRenderer = new VPathRenderer();
boolean noSizeTag = true;
boolean noViewportTag = true;
@@ -336,23 +280,18 @@
path.inflate(res, attrs, theme);
currentGroup.add(path);
noPathTag = false;
- } else if (SHAPE_ANIMATION.equals(tagName)) {
- final VAnimation anim = new VAnimation();
- anim.inflate(animatedPath.mGroupList, res, attrs, theme);
- animatedPath.addAnimation(anim);
} else if (SHAPE_SIZE.equals(tagName)) {
- animatedPath.parseSize(res, attrs);
+ pathRenderer.parseSize(res, attrs);
noSizeTag = false;
} else if (SHAPE_VIEWPORT.equals(tagName)) {
- animatedPath.parseViewport(res, attrs);
+ pathRenderer.parseViewport(res, attrs);
noViewportTag = false;
} else if (SHAPE_GROUP.equals(tagName)) {
currentGroup = new VGroup();
- animatedPath.mGroupList.add(currentGroup);
+ pathRenderer.mGroupList.add(currentGroup);
noGroupTag = false;
} else if (SHAPE_VECTOR.equals(tagName)) {
final TypedArray a = res.obtainAttributes(attrs, R.styleable.VectorDrawable);
- animatedPath.setTrigger(a.getInteger(R.styleable.VectorDrawable_trigger, 0));
// Parsing the version information.
// Right now, we only support version "1".
@@ -403,23 +342,23 @@
}
// post parse cleanup
- animatedPath.parseFinish();
- return animatedPath;
+ pathRenderer.parseFinish();
+ return pathRenderer;
}
- private void setAnimatedPath(VAnimatedPath animatedPath) {
- mVectorState.mVAnimatedPath = animatedPath;
+ private void setPathRenderer(VPathRenderer pathRenderer) {
+ mVectorState.mVPathRenderer = pathRenderer;
}
private static class VectorDrawableState extends ConstantState {
int mChangingConfigurations;
- VAnimatedPath mVAnimatedPath;
+ VPathRenderer mVPathRenderer;
Rect mPadding;
public VectorDrawableState(VectorDrawableState copy) {
if (copy != null) {
mChangingConfigurations = copy.mChangingConfigurations;
- mVAnimatedPath = new VAnimatedPath(copy.mVAnimatedPath);
+ mVPathRenderer = new VPathRenderer(copy.mVPathRenderer);
mPadding = new Rect(copy.mPadding);
}
}
@@ -445,35 +384,16 @@
}
}
- private static class VAnimatedPath {
- private static final int [] TRIGGER_MAP = {
- 0,
- R.attr.state_pressed,
- R.attr.state_focused,
- R.attr.state_hovered,
- R.attr.state_selected,
- R.attr.state_checkable,
- R.attr.state_checked,
- R.attr.state_activated,
- R.attr.state_focused
- };
-
+ private static class VPathRenderer {
private final Path mPath = new Path();
private final Path mRenderPath = new Path();
private final Matrix mMatrix = new Matrix();
- private ArrayList<VAnimation> mCurrentAnimList;
private VPath[] mCurrentPaths;
private Paint mStrokePaint;
private Paint mFillPaint;
private PathMeasure mPathMeasure;
- private int[] mCurrentState = new int[0];
- private float mAnimationValue;
- private long mTotalDuration;
- private int mTrigger;
- private boolean mTriggerState;
-
final ArrayList<VGroup> mGroupList = new ArrayList<VGroup>();
float mBaseWidth = 1;
@@ -481,11 +401,10 @@
float mViewportWidth;
float mViewportHeight;
- public VAnimatedPath() {
+ public VPathRenderer() {
}
- public VAnimatedPath(VAnimatedPath copy) {
- mCurrentAnimList = new ArrayList<VAnimation>(copy.mCurrentAnimList);
+ public VPathRenderer(VPathRenderer copy) {
mGroupList.addAll(copy.mGroupList);
if (copy.mCurrentPaths != null) {
mCurrentPaths = new VPath[copy.mCurrentPaths.length];
@@ -493,15 +412,11 @@
mCurrentPaths[i] = new VPath(copy.mCurrentPaths[i]);
}
}
- mAnimationValue = copy.mAnimationValue; // time goes from 0 to 1
mBaseWidth = copy.mBaseWidth;
mBaseHeight = copy.mBaseHeight;
mViewportWidth = copy.mViewportHeight;
mViewportHeight = copy.mViewportHeight;
- mTotalDuration = copy.mTotalDuration;
- mTrigger = copy.mTrigger;
- mCurrentState = new int[0];
}
public boolean canApplyTheme() {
@@ -516,14 +431,6 @@
}
}
- final ArrayList<VAnimation> anims = mCurrentAnimList;
- for (int i = anims.size() - 1; i >= 0; i--) {
- final VAnimation anim = anims.get(i);
- if (anim.canApplyTheme()) {
- return true;
- }
- }
-
return false;
}
@@ -539,70 +446,6 @@
}
}
- final ArrayList<VAnimation> anims = mCurrentAnimList;
- for (int i = anims.size() - 1; i >= 0; i--) {
- final VAnimation anim = anims.get(i);
- if (anim.canApplyTheme()) {
- anim.applyTheme(t);
- }
- }
- }
-
- public void setTrigger(int trigger){
- mTrigger = VAnimatedPath.getStateForTrigger(trigger);
- }
-
- public long getTotalAnimationDuration() {
- mTotalDuration = 0;
- int size = mCurrentAnimList.size();
- for (int i = 0; i < size; i++) {
- VAnimation vAnimation = mCurrentAnimList.get(i);
- long t = vAnimation.getTotalDuration();
- if (t == -1) {
- mTotalDuration = -1;
- return -1;
- }
- mTotalDuration = Math.max(mTotalDuration, t);
- }
-
- return mTotalDuration;
- }
-
- public float getValue() {
- return mAnimationValue;
- }
-
- /**
- * @param value the point along the animations to show typically between 0.0f and 1.0f
- * @return true if you need to keep repeating
- */
- public boolean setAnimationFraction(float value) {
- getTotalAnimationDuration();
-
- long animationTime = (long) (value * mTotalDuration);
-
- final int len = mCurrentPaths.length;
- for (int i = 0; i < len; i++) {
- animationTime =
- (long) ((mTotalDuration == -1) ? value * 1000 : mTotalDuration * value);
-
- final VPath path = mCurrentPaths[i];
- final int size = mCurrentAnimList.size();
- for (int j = 0; j < size; j++) {
- final VAnimation vAnimation = mCurrentAnimList.get(j);
- if (vAnimation.doesAdjustPath(path)) {
- mCurrentPaths[i] = vAnimation.getPathAtTime(animationTime, path);
- }
- }
- }
-
- mAnimationValue = value;
-
- if (mTotalDuration == -1) {
- return true;
- } else {
- return animationTime < mTotalDuration;
- }
}
public void draw(Canvas canvas, int w, int h) {
@@ -612,7 +455,7 @@
}
for (int i = 0; i < mCurrentPaths.length; i++) {
- if (mCurrentPaths[i] != null && mCurrentPaths[i].isVisible(mCurrentState)) {
+ if (mCurrentPaths[i] != null) {
drawPath(mCurrentPaths[i], canvas, w, h);
}
}
@@ -694,34 +537,10 @@
}
/**
- * Ensure there is at least one animation for every path in group (linking them by names)
* Build the "current" path based on the first group
* TODO: improve memory use & performance or move to C++
*/
public void parseFinish() {
- final HashMap<String, VAnimation> newAnimations = new HashMap<String, VAnimation>();
- for (VGroup group : mGroupList) {
- for (VPath vPath : group.getPaths()) {
- if (!vPath.mAnimated) {
- VAnimation ap = null;
-
- if (!newAnimations.containsKey(vPath.getID())) {
- newAnimations.put(vPath.getID(), ap = new VAnimation());
- } else {
- ap = newAnimations.get(vPath.getID());
- }
-
- ap.addPath(vPath);
- vPath.mAnimated = true;
- }
- }
- }
-
- if (mCurrentAnimList == null) {
- mCurrentAnimList = new ArrayList<VectorDrawable.VAnimation>();
- }
- mCurrentAnimList.addAll(newAnimations.values());
-
final Collection<VPath> paths = mGroupList.get(0).getPaths();
mCurrentPaths = paths.toArray(new VPath[paths.size()]);
for (int i = 0; i < mCurrentPaths.length; i++) {
@@ -729,34 +548,6 @@
}
}
- public void setState(int[] state) {
- mCurrentState = Arrays.copyOf(state, state.length);
- }
-
- int getTrigger(int []state){
- if (mTrigger == 0) return 0;
- for (int i = 0; i < state.length; i++) {
- if (state[i] == mTrigger){
- if (mTriggerState)
- return 0;
- mTriggerState = true;
- return 1;
- }
- }
- if (mTriggerState) {
- mTriggerState = false;
- return -1;
- }
- return 0;
- }
-
- public void addAnimation(VAnimation anim) {
- if (mCurrentAnimList == null) {
- mCurrentAnimList = new ArrayList<VectorDrawable.VAnimation>();
- }
- mCurrentAnimList.add(anim);
- }
-
private void parseViewport(Resources r, AttributeSet attrs)
throws XmlPullParserException {
final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableViewport);
@@ -781,329 +572,6 @@
a.recycle();
}
- private static final int getStateForTrigger(int trigger) {
- return TRIGGER_MAP[trigger];
- }
- }
-
- private static class VAnimation {
- private static final String SEPARATOR = ",";
-
- private static final int DIRECTION_FORWARD = 0;
- private static final int DIRECTION_IN_AND_OUT = 1;
-
- public enum Style {
- INTERPOLATE, CROSSFADE, WIPE
- }
-
- private final HashSet<String> mSeqMap = new HashSet<String>();
-
- private Interpolator mAnimInterpolator = new AccelerateDecelerateInterpolator();
- private VPath[] mPaths = new VPath[0];
- private long[] mDuration = { DEFAULT_DURATION };
-
- private int[] mThemeAttrs;
- private Style mStyle;
- private int mLimitProperty = 0;
- private long mStartOffset;
- private long mRepeat = 1;
- private long mWipeDirection;
- private int mMode = DIRECTION_FORWARD;
- private int mInterpolatorType;
- private String mId;
-
- public VAnimation() {
- // Empty constructor.
- }
-
- public void inflate(ArrayList<VGroup> groups, Resources r, AttributeSet attrs, Theme theme)
- throws XmlPullParserException {
- String value;
- String[] sp;
- int name;
-
- final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableAnimation);
- final int[] themeAttrs = a.extractThemeAttrs();
- mThemeAttrs = themeAttrs;
-
- value = a.getString(R.styleable.VectorDrawableAnimation_sequence);
- if (value != null) {
- sp = value.split(SEPARATOR);
- final VectorDrawable.VPath[] paths = new VectorDrawable.VPath[sp.length];
-
- for (int j = 0; j < sp.length; j++) {
- mSeqMap.add(sp[j].trim());
-
- final VectorDrawable.VPath path = groups.get(j).get(sp[j]);
- if (path == null) {
- throw new XmlPullParserException(a.getPositionDescription()
- + " missing path with name: " + sp[j]);
- }
-
- path.mAnimated = true;
- paths[j] = path;
- }
-
- setPaths(paths);
- }
-
- name = R.styleable.VectorDrawableAnimation_durations;
- value = a.getString(name);
- if (value != null) {
- long totalDuration = 0;
- sp = value.split(SEPARATOR);
-
- final long[] dur = new long[sp.length];
- for (int j = 0; j < dur.length; j++) {
- dur[j] = Long.parseLong(sp[j]);
- totalDuration += dur[j];
- }
-
- if (totalDuration == 0){
- throw new XmlPullParserException(a.getPositionDescription()
- + " total duration must not be zero");
- }
-
- setDuration(dur);
- }
-
- setLimitProperty(a.getInt(R.styleable.VectorDrawableAnimation_limitTo, 0));
- setRepeat(a.getInt(R.styleable.VectorDrawableAnimation_repeatCount, 1));
- setStartOffset(a.getInt(R.styleable.VectorDrawableAnimation_startDelay, 0));
- setMode(a.getInt(R.styleable.VectorDrawableAnimation_repeatStyle, 0));
-
- fixMissingParameters();
-
- a.recycle();
- }
-
- public boolean canApplyTheme() {
- return mThemeAttrs != null;
- }
-
- public void applyTheme(Theme t) {
- // TODO: Apply theme.
- }
-
- public boolean doesAdjustPath(VPath path) {
- return mSeqMap.contains(path.getID());
- }
-
- public String getId() {
- if (mId == null) {
- mId = mPaths[0].getID();
- for (int i = 1; i < mPaths.length; i++) {
- mId += mPaths[i].getID();
- }
- }
- return mId;
- }
-
- public String getPathName() {
- return mPaths[0].getID();
- }
-
- public Style getStyle() {
- return mStyle;
- }
-
- public void setStyle(Style style) {
- mStyle = style;
- }
-
- public int getLimitProperty() {
- return mLimitProperty;
- }
-
- public void setLimitProperty(int limitProperty) {
- mLimitProperty = limitProperty;
- }
-
- public long[] getDuration() {
- return mDuration;
- }
-
- public void setDuration(long[] duration) {
- mDuration = duration;
- }
-
- public long getRepeat() {
- return mRepeat;
- }
-
- public void setRepeat(long repeat) {
- mRepeat = repeat;
- }
-
- public long getStartOffset() {
- return mStartOffset;
- }
-
- public void setStartOffset(long startOffset) {
- mStartOffset = startOffset;
- }
-
- public long getWipeDirection() {
- return mWipeDirection;
- }
-
- public void setWipeDirection(long wipeDirection) {
- mWipeDirection = wipeDirection;
- }
-
- public int getMode() {
- return mMode;
- }
-
- public void setMode(int mode) {
- mMode = mode;
- }
-
- public int getInterpolator() {
- return mInterpolatorType;
- }
-
- public void setInterpolator(int interpolator) {
- mInterpolatorType = interpolator;
- }
-
- /**
- * compute the total time in milliseconds
- *
- * @return the total time in milliseconds the animation will take
- */
- public long getTotalDuration() {
- long total = mStartOffset;
- if (getRepeat() == -1) {
- return -1;
- }
- for (int i = 0; i < mDuration.length; i++) {
- if (mRepeat > 1) {
- total += mDuration[i] * mRepeat;
- } else {
- total += mDuration[i];
- }
- }
- return total;
- }
-
- public void setPaths(VPath[] paths) {
- mPaths = paths;
- }
-
- public void addPath(VPath path) {
- mPaths = Arrays.copyOf(mPaths, mPaths.length + 1);
- mPaths[mPaths.length - 1] = path;
- }
-
- public boolean containsPath(String pathid) {
- for (int i = 0; i < mPaths.length; i++) {
- if (mPaths[i].getID().equals(pathid)) {
- return true;
- }
- }
- return false;
- }
-
- public void interpolate(VPath p1, VPath p2, float time, VPath dest) {
- VPath.interpolate(time, p1, p2, dest, mLimitProperty);
- }
-
- public VPath getPathAtTime(long milliseconds, VPath dest) {
- if (mPaths.length == 1) {
- dest.copyFrom(mPaths[0]);
- return dest;
- }
- long point = milliseconds - mStartOffset;
- if (point < 0) {
- point = 0;
- }
- float time = 0;
- long sum = mDuration[0];
- for (int i = 1; i < mDuration.length; i++) {
- sum += mDuration[i];
- }
-
- if (mRepeat > 1) {
- time = point / (float) (sum * mRepeat);
- time = mAnimInterpolator.getInterpolation(time);
-
- if (mMode == DIRECTION_IN_AND_OUT) {
- point = ((long) (time * sum * 2 * mRepeat)) % (sum * 2);
- if (point > sum) {
- point = sum * 2 - point;
- }
- } else {
- point = ((long) (time * sum * mRepeat)) % sum;
- }
- } else if (mRepeat == 1) {
- time = point / (float) (sum * mRepeat);
- time = mAnimInterpolator.getInterpolation(time);
- if (mMode == DIRECTION_IN_AND_OUT) {
- point = ((long) (time * sum * 2 * mRepeat));
- if (point > sum) {
- point = sum * 2 - point;
- }
- } else {
- point = Math.min(((long) (time * sum * mRepeat)), sum);
- }
-
- } else { // repeat = -1
- if (mMode == DIRECTION_IN_AND_OUT) {
- point = point % (sum * 2);
- if (point > sum) {
- point = sum * 2 - point;
- }
- time = point / (float) sum;
- } else {
- point = point % sum;
- time = point / (float) sum;
- }
- }
-
- int transition = 0;
- while (point > mDuration[transition]) {
- point -= mDuration[transition++];
- }
- if (mPaths.length > (transition + 1)) {
- if (mPaths[transition].getID() != dest.getID()) {
- dest.copyFrom(mPaths[transition]);
- }
- interpolate(mPaths[transition], mPaths[transition + 1],
- point / (float) mDuration[transition], dest);
- } else {
- interpolate(mPaths[transition], mPaths[transition], 0, dest);
- }
- return dest;
- }
-
- void fixMissingParameters() {
- // fix missing points
- float rotation = Float.NaN;
- float rotationY = Float.NaN;
- float rotationX = Float.NaN;
- for (int i = 0; i < mPaths.length; i++) {
- if (mPaths[i].mPivotX > 0) {
- rotationX = mPaths[i].mPivotX;
- }
- if (mPaths[i].mPivotY > 0) {
- rotationY = mPaths[i].mPivotY;
- }
- if (mPaths[i].mRotate > 0) {
- rotation = mPaths[i].mRotate;
- }
- }
- if (rotation > 0) {
- for (int i = 0; i < mPaths.length; i++) {
- if (mPaths[i].mPivotX == 0) {
- mPaths[i].mPivotX = rotationX;
- }
- if (mPaths[i].mPivotY == 0) {
- mPaths[i].mPivotY = rotationY;
- }
- }
- }
- }
}
private static class VGroup {
@@ -1116,10 +584,6 @@
mVGList.add(path);
}
- public VPath get(String name) {
- return mVGPathMap.get(name);
- }
-
/**
* Must return in order of adding
* @return ordered list of paths
@@ -1128,23 +592,9 @@
return mVGList;
}
- public int size() {
- return mVGPathMap.size();
- }
}
private static class VPath {
- private static final int LIMIT_ALL = 0;
- private static final int LIMIT_PATH = 1;
- private static final int LIMIT_ROTATE = 2;
- private static final int LIMIT_TRIM_PATH_START = 3;
- private static final int LIMIT_TRIM_PATH_OFFSET = 5;
- private static final int LIMIT_TRIM_PATH_END = 4;
-
- private static final int STATE_UNDEFINED=0;
- private static final int STATE_TRUE=1;
- private static final int STATE_FALSE=2;
-
private static final int MAX_STATES = 10;
private int[] mThemeAttrs;
@@ -1165,7 +615,6 @@
float mTrimPathEnd = 1;
float mTrimPathOffset = 0;
- boolean mAnimated = false;
boolean mClip = false;
Paint.Cap mStrokeLineCap = Paint.Cap.BUTT;
Paint.Join mStrokeLineJoin = Paint.Join.MITER;
@@ -1176,7 +625,6 @@
private int[] mCheckState = new int[MAX_STATES];
private boolean[] mCheckValue = new boolean[MAX_STATES];
private int mNumberOfStates = 0;
- private int mNumberOfTrue = 0;
public VPath() {
// Empty constructor.
@@ -1186,38 +634,6 @@
copyFrom(p);
}
- public void addStateFilter(int state, boolean condition) {
- int k = 0;
- while (k < mNumberOfStates) {
- if (mCheckState[mNumberOfStates] == state)
- break;
- k++;
- }
- mCheckState[k] = state;
- mCheckValue[k] = condition;
- if (k==mNumberOfStates){
- mNumberOfStates++;
- }
- if (condition) {
- mNumberOfTrue++;
- }
- }
-
- private int getState(int state){
- for (int i = 0; i < mNumberOfStates; i++) {
- if (mCheckState[mNumberOfStates] == state){
- return (mCheckValue[i])?STATE_TRUE:STATE_FALSE;
- }
- }
- return STATE_UNDEFINED;
- }
- /**
- * @return the name of the path
- */
- public String getName() {
- return mId;
- }
-
public void toPath(Path path) {
path.reset();
if (mNode != null) {
@@ -1342,27 +758,6 @@
R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart);
}
- // TODO: Consider replacing this with existing state attributes.
- final int[] states = {
- R.styleable.VectorDrawablePath_state_activated,
- R.styleable.VectorDrawablePath_state_checkable,
- R.styleable.VectorDrawablePath_state_checked,
- R.styleable.VectorDrawablePath_state_enabled,
- R.styleable.VectorDrawablePath_state_focused,
- R.styleable.VectorDrawablePath_state_hovered,
- R.styleable.VectorDrawablePath_state_pressed,
- R.styleable.VectorDrawablePath_state_selected,
- R.styleable.VectorDrawablePath_state_window_focused
- };
-
- final int N = states.length;
- for (int i = 0; i < N; i++) {
- final int state = states[i];
- if (a.hasValue(state)) {
- addStateFilter(state, a.getBoolean(state, false));
- }
- }
-
updateColorAlphas();
a.recycle();
@@ -1530,7 +925,6 @@
mRotate = p1.mRotate;
mPivotX = p1.mPivotX;
mPivotY = p1.mPivotY;
- mAnimated = p1.mAnimated;
mTrimPathStart = p1.mTrimPathStart;
mTrimPathEnd = p1.mTrimPathEnd;
mTrimPathOffset = p1.mTrimPathOffset;
@@ -1545,118 +939,6 @@
mFillRule = p1.mFillRule;
}
-
- public static VPath interpolate(float t, VPath p1, VPath p2, VPath returnPath, int limit) {
- if (limit == LIMIT_ALL || limit == LIMIT_PATH) {
- if (returnPath.mNode == null || returnPath.mNode.length != p1.mNode.length) {
- returnPath.mNode = new VNode[p1.mNode.length];
- }
- for (int i = 0; i < returnPath.mNode.length; i++) {
- if (returnPath.mNode[i] == null) {
- returnPath.mNode[i] = new VNode(p1.mNode[i], p2.mNode[i], t);
- } else {
- returnPath.mNode[i].interpolate(p1.mNode[i], p2.mNode[i], t);
- }
- }
- }
- float t1 = 1 - t;
- switch (limit) {
- case LIMIT_ALL:
- returnPath.mRotate = t1 * p1.mRotate + t * p2.mRotate;
- returnPath.mPivotX = t1 * p1.mPivotX + t * p2.mPivotX;
- returnPath.mPivotY = t1 * p1.mPivotY + t * p2.mPivotY;
- returnPath.mClip = p1.mClip | p2.mClip;
-
- returnPath.mTrimPathStart = t1 * p1.mTrimPathStart + t * p2.mTrimPathStart;
- returnPath.mTrimPathEnd = t1 * p1.mTrimPathEnd + t * p2.mTrimPathEnd;
- returnPath.mTrimPathOffset = t1 * p1.mTrimPathOffset + t * p2.mTrimPathOffset;
- returnPath.mStrokeMiterlimit =
- t1 * p1.mStrokeMiterlimit + t * p2.mStrokeMiterlimit;
- returnPath.mStrokeLineCap = p1.mStrokeLineCap;
- if (returnPath.mStrokeLineCap == null) {
- returnPath.mStrokeLineCap = p2.mStrokeLineCap;
- }
- returnPath.mStrokeLineJoin = p1.mStrokeLineJoin;
- if (returnPath.mStrokeLineJoin == null) {
- returnPath.mStrokeLineJoin = p2.mStrokeLineJoin;
- }
- returnPath.mFillRule = p1.mFillRule;
-
- returnPath.mStrokeColor = rgbInterpolate(t, p1.mStrokeColor, p2.mStrokeColor);
- returnPath.mFillColor = rgbInterpolate(t, p1.mFillColor, p2.mFillColor);
- returnPath.mStrokeWidth = t1 * p1.mStrokeWidth + t * p2.mStrokeWidth;
- returnPath.mNumberOfStates = p1.mNumberOfStates;
- for (int i = 0; i < returnPath.mNumberOfStates; i++) {
- returnPath.mCheckState[i] = p1.mCheckState[i];
- returnPath.mCheckValue[i] = p1.mCheckValue[i];
- }
- for (int i = 0; i < p2.mNumberOfStates; i++) {
- returnPath.addStateFilter(p2.mCheckState[i], p2.mCheckValue[i]);
- }
-
- int count = 0;
- for (int i = 0; i < returnPath.mNumberOfStates; i++) {
- if (returnPath.mCheckValue[i]) {
- count++;
- }
- }
- returnPath.mNumberOfTrue = count;
- break;
- case LIMIT_ROTATE:
- returnPath.mRotate = t1 * p1.mRotate + t * p2.mRotate;
- break;
- case LIMIT_TRIM_PATH_END:
- returnPath.mTrimPathEnd = t1 * p1.mTrimPathEnd + t * p2.mTrimPathEnd;
- break;
- case LIMIT_TRIM_PATH_OFFSET:
- returnPath.mTrimPathOffset = t1 * p1.mTrimPathOffset + t * p2.mTrimPathOffset;
- break;
- case LIMIT_TRIM_PATH_START:
- returnPath.mTrimPathStart = t1 * p1.mTrimPathStart + t * p2.mTrimPathStart;
- break;
- }
- return returnPath;
- }
-
- private static int rgbInterpolate(float fraction, int startColor, int endColor) {
- if (startColor == endColor) {
- return startColor;
- } else if (startColor == 0) {
- return endColor;
- } else if (endColor == 0) {
- return startColor;
- }
-
- final int startA = (startColor >> 24) & 0xff;
- final int startR = (startColor >> 16) & 0xff;
- final int startG = (startColor >> 8) & 0xff;
- final int startB = startColor & 0xff;
-
- final int endA = (endColor >> 24) & 0xff;
- final int endR = (endColor >> 16) & 0xff;
- final int endG = (endColor >> 8) & 0xff;
- final int endB = endColor & 0xff;
-
- return ((startA + (int)(fraction * (endA - startA))) << 24) |
- ((startR + (int)(fraction * (endR - startR))) << 16) |
- ((startG + (int)(fraction * (endG - startG))) << 8) |
- ((startB + (int)(fraction * (endB - startB))));
- }
-
- public boolean isVisible(int[] state) {
- int match = 0;
- for (int i = 0; i < state.length; i++) {
- int v = getState(state[i]);
- if (v != STATE_UNDEFINED) {
- if (v==STATE_TRUE) {
- match++;
- } else {
- return false;
- }
- }
- }
- return match == mNumberOfTrue;
- }
}
private static class VNode {
@@ -1673,25 +955,6 @@
mParams = Arrays.copyOf(n.mParams, n.mParams.length);
}
- public VNode(VNode n1, VNode n2, float t) {
- mType = n1.mType;
- mParams = new float[n1.mParams.length];
- interpolate(n1, n2, t);
- }
-
- private boolean match(VNode n) {
- if (n.mType != mType) {
- return false;
- }
- return (mParams.length == n.mParams.length);
- }
-
- public void interpolate(VNode n1, VNode n2, float t) {
- for (int i = 0; i < n1.mParams.length; i++) {
- mParams[i] = n1.mParams[i] * (1 - t) + n2.mParams[i] * t;
- }
- }
-
public static void createPath(VNode[] node, Path path) {
float[] current = new float[4];
char previousCommand = 'm';
@@ -1747,7 +1010,6 @@
break;
}
for (int k = 0; k < val.length; k += incr) {
- // TODO: build test to prove all permutations work
switch (cmd) {
case 'm': // moveto - Start a new sub-path (relative)
path.rMoveTo(val[k + 0], val[k + 1]);
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index eb0cac8..2cadf09 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -6,6 +6,7 @@
ifeq ($(USE_OPENGL_RENDERER),true)
LOCAL_SRC_FILES := \
utils/Blur.cpp \
+ utils/GLUtils.cpp \
utils/SortedListImpl.cpp \
thread/TaskManager.cpp \
font/CacheTexture.cpp \
@@ -53,7 +54,7 @@
TextureCache.cpp \
TextDropShadowCache.cpp
- # RenderThread stuff
+# RenderThread stuff
LOCAL_SRC_FILES += \
renderthread/CanvasContext.cpp \
renderthread/DrawFrameTask.cpp \
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 3d58964..45b6624 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -190,7 +190,7 @@
// Overlapping other operations is only allowed for text without shadow. For other ops,
// multiDraw isn't guaranteed to overdraw correctly
- if (!isTextBatch || state->mDrawModifiers.mHasShadow) {
+ if (!isTextBatch || op->hasTextShadow()) {
if (intersects(state->mBounds)) return false;
}
const DeferredDisplayState* lhs = state;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index ce92beb..f1d70eb 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -183,6 +183,10 @@
return OpenGLRenderer::getAlphaDirect(mPaint);
}
+ virtual bool hasTextShadow() const {
+ return false;
+ }
+
inline float strokeWidthOutset() {
// since anything AA stroke with less than 1.0 pixel width is drawn with an alpha-reduced
// 1.0 stroke, treat 1.0 as minimum.
@@ -244,11 +248,11 @@
bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
localBounds.set(mLocalBounds);
- if (drawModifiers.mHasShadow) {
- // TODO: inspect paint's looper directly
+ OpenGLRenderer::TextShadow textShadow;
+ if (OpenGLRenderer::getTextShadow(mPaint, &textShadow)) {
Rect shadow(mLocalBounds);
- shadow.translate(drawModifiers.mShadowDx, drawModifiers.mShadowDy);
- shadow.outset(drawModifiers.mShadowRadius);
+ shadow.translate(textShadow.dx, textShadow.dx);
+ shadow.outset(textShadow.radius);
localBounds.unionWith(shadow);
}
return true;
@@ -619,41 +623,6 @@
SkiaShader* mShader;
};
-class ResetShadowOp : public StateOp {
-public:
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
- renderer.resetShadow();
- }
-
- virtual void output(int level, uint32_t logFlags) const {
- OP_LOGS("ResetShadow");
- }
-
- virtual const char* name() { return "ResetShadow"; }
-};
-
-class SetupShadowOp : public StateOp {
-public:
- SetupShadowOp(float radius, float dx, float dy, int color)
- : mRadius(radius), mDx(dx), mDy(dy), mColor(color) {}
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
- renderer.setupShadow(mRadius, mDx, mDy, mColor);
- }
-
- virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("SetupShadow, radius %f, %f, %f, color %#x", mRadius, mDx, mDy, mColor);
- }
-
- virtual const char* name() { return "SetupShadow"; }
-
-private:
- float mRadius;
- float mDx;
- float mDy;
- int mColor;
-};
-
class ResetPaintFilterOp : public StateOp {
public:
virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
@@ -1351,6 +1320,10 @@
OP_LOG("Draw some text, %d bytes", mBytesCount);
}
+ virtual bool hasTextShadow() const {
+ return OpenGLRenderer::hasTextShadow(mPaint);
+ }
+
virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
const DeferredDisplayState& state) {
const SkPaint* paint = getPaint(renderer);
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 8afd106..c2ce6ed 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -410,16 +410,6 @@
addStateOp(new (alloc()) SetupShaderOp(shader));
}
-void DisplayListRenderer::resetShadow() {
- addStateOp(new (alloc()) ResetShadowOp());
- OpenGLRenderer::resetShadow();
-}
-
-void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) {
- addStateOp(new (alloc()) SetupShadowOp(radius, dx, dy, color));
- OpenGLRenderer::setupShadow(radius, dx, dy, color);
-}
-
void DisplayListRenderer::resetPaintFilter() {
addStateOp(new (alloc()) ResetPaintFilterOp());
}
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 25e78c1..185179a 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -102,9 +102,6 @@
virtual void resetShader();
virtual void setupShader(SkiaShader* shader);
- virtual void resetShadow();
- virtual void setupShadow(float radius, float dx, float dy, int color);
-
virtual void resetPaintFilter();
virtual void setupPaintFilter(int clearBits, int setBits);
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index f06106b..2268386 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -482,8 +482,8 @@
sy = copysignf(sqrtf(len), data[mat4::kScaleY]);
}
-void Matrix4::dump() const {
- ALOGD("Matrix4[simple=%d, type=0x%x", isSimple(), getType());
+void Matrix4::dump(const char* label) const {
+ ALOGD("%s[simple=%d, type=0x%x", label ? label : "Matrix4", isSimple(), getType());
ALOGD(" %f %f %f %f", data[kScaleX], data[kSkewX], data[8], data[kTranslateX]);
ALOGD(" %f %f %f %f", data[kSkewY], data[kScaleY], data[9], data[kTranslateY]);
ALOGD(" %f %f %f %f", data[2], data[6], data[kScaleZ], data[kTranslateZ]);
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index 26cb05f..e33a001 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -209,7 +209,7 @@
void decomposeScale(float& sx, float& sy) const;
- void dump() const;
+ void dump(const char* label = NULL) const;
static const Matrix4& identity();
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 6de369c..5a977c8 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -37,6 +37,7 @@
#include "PathTessellator.h"
#include "Properties.h"
#include "ShadowTessellator.h"
+#include "utils/GLUtils.h"
#include "Vector.h"
#include "VertexBuffer.h"
@@ -296,24 +297,7 @@
if (!suppressErrorChecks()) {
#if DEBUG_OPENGL
- GLenum status = GL_NO_ERROR;
- while ((status = glGetError()) != GL_NO_ERROR) {
- ALOGD("GL error from OpenGLRenderer: 0x%x", status);
- switch (status) {
- case GL_INVALID_ENUM:
- ALOGE(" GL_INVALID_ENUM");
- break;
- case GL_INVALID_VALUE:
- ALOGE(" GL_INVALID_VALUE");
- break;
- case GL_INVALID_OPERATION:
- ALOGE(" GL_INVALID_OPERATION");
- break;
- case GL_OUT_OF_MEMORY:
- ALOGE(" Out of memory!");
- break;
- }
- }
+ GLUtils::dumpGLErrors();
#endif
#if DEBUG_MEMORY_USAGE
@@ -2654,28 +2638,32 @@
FontRenderer& fontRenderer, int alpha, float x, float y) {
mCaches.activeTexture(0);
+ TextShadow textShadow;
+ if (!getTextShadow(paint, &textShadow)) {
+ LOG_ALWAYS_FATAL("failed to query shadow attributes");
+ }
+
// NOTE: The drop shadow will not perform gamma correction
// if shader-based correction is enabled
mCaches.dropShadowCache.setFontRenderer(fontRenderer);
const ShadowTexture* shadow = mCaches.dropShadowCache.get(
- paint, text, bytesCount, count, mDrawModifiers.mShadowRadius, positions);
+ paint, text, bytesCount, count, textShadow.radius, positions);
// If the drop shadow exceeds the max texture size or couldn't be
// allocated, skip drawing
if (!shadow) return;
const AutoTexture autoCleanup(shadow);
- const float sx = x - shadow->left + mDrawModifiers.mShadowDx;
- const float sy = y - shadow->top + mDrawModifiers.mShadowDy;
+ const float sx = x - shadow->left + textShadow.dx;
+ const float sy = y - shadow->top + textShadow.dy;
- const int shadowAlpha = ((mDrawModifiers.mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
- int shadowColor = mDrawModifiers.mShadowColor;
+ const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * mSnapshot->alpha;
if (mDrawModifiers.mShader) {
- shadowColor = 0xffffffff;
+ textShadow.color = SK_ColorWHITE;
}
setupDraw();
setupDrawWithTexture(true);
- setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha);
+ setupDrawAlpha8Color(textShadow.color, shadowAlpha < 255 ? shadowAlpha : alpha);
setupDrawColorFilter(getColorFilter(paint));
setupDrawShader();
setupDrawBlending(paint, true);
@@ -2692,7 +2680,7 @@
}
bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
- float alpha = (mDrawModifiers.mHasShadow ? 1.0f : paint->getAlpha()) * mSnapshot->alpha;
+ float alpha = (hasTextShadow(paint) ? 1.0f : paint->getAlpha()) * mSnapshot->alpha;
return alpha == 0.0f && getXfermode(paint->getXfermode()) == SkXfermode::kSrcOver_Mode;
}
@@ -2724,7 +2712,7 @@
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
- if (CC_UNLIKELY(mDrawModifiers.mHasShadow)) {
+ if (CC_UNLIKELY(hasTextShadow(paint))) {
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer,
alpha, 0.0f, 0.0f);
}
@@ -2801,7 +2789,7 @@
FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
- if (CC_UNLIKELY(mDrawModifiers.mHasShadow)) {
+ if (CC_UNLIKELY(hasTextShadow(paint))) {
fontRenderer.setFont(paint, mat4::identity());
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer,
alpha, oldX, oldY);
@@ -3022,22 +3010,6 @@
}
///////////////////////////////////////////////////////////////////////////////
-// Drop shadow
-///////////////////////////////////////////////////////////////////////////////
-
-void OpenGLRenderer::resetShadow() {
- mDrawModifiers.mHasShadow = false;
-}
-
-void OpenGLRenderer::setupShadow(float radius, float dx, float dy, int color) {
- mDrawModifiers.mHasShadow = true;
- mDrawModifiers.mShadowRadius = radius;
- mDrawModifiers.mShadowDx = dx;
- mDrawModifiers.mShadowDy = dy;
- mDrawModifiers.mShadowColor = color;
-}
-
-///////////////////////////////////////////////////////////////////////////////
// Draw filters
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 4de52ac..1d46945 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -29,6 +29,7 @@
#include <SkShader.h>
#include <SkXfermode.h>
+#include <utils/Blur.h>
#include <utils/Functor.h>
#include <utils/RefBase.h>
#include <utils/SortedVector.h>
@@ -72,13 +73,6 @@
SkiaShader* mShader;
float mOverrideLayerAlpha;
- // Drop shadow
- bool mHasShadow;
- float mShadowRadius;
- float mShadowDx;
- float mShadowDy;
- int mShadowColor;
-
// Draw filters
bool mHasDrawFilter;
int mPaintFilterClearBits;
@@ -226,9 +220,6 @@
virtual void resetShader();
virtual void setupShader(SkiaShader* shader);
- virtual void resetShadow();
- virtual void setupShadow(float radius, float dx, float dy, int color);
-
virtual void resetPaintFilter();
virtual void setupPaintFilter(int clearBits, int setBits);
@@ -316,6 +307,31 @@
return paint->getAlpha();
}
+ struct TextShadow {
+ SkScalar radius;
+ float dx;
+ float dy;
+ SkColor color;
+ };
+
+ static inline bool getTextShadow(const SkPaint* paint, TextShadow* textShadow) {
+ SkDrawLooper::BlurShadowRec blur;
+ if (paint && paint->getLooper() && paint->getLooper()->asABlurShadow(&blur)) {
+ if (textShadow) {
+ textShadow->radius = Blur::convertSigmaToRadius(blur.fSigma);
+ textShadow->dx = blur.fOffset.fX;
+ textShadow->dy = blur.fOffset.fY;
+ textShadow->color = blur.fColor;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ static inline bool hasTextShadow(const SkPaint* paint) {
+ return getTextShadow(paint, NULL);
+ }
+
/**
* Return the best transform to use to rasterize text given a full
* transform matrix.
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index 92964a8..f38d8b7 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -175,6 +175,10 @@
bottom += dy;
}
+ void inset(float delta) {
+ outset(-delta);
+ }
+
void outset(float delta) {
left -= delta;
top -= delta;
@@ -230,8 +234,8 @@
bottom = ceilf(bottom);
}
- void dump() const {
- ALOGD("Rect[l=%f t=%f r=%f b=%f]", left, top, right, bottom);
+ void dump(const char* label) const {
+ ALOGD("%s[l=%f t=%f r=%f b=%f]", label ? label : "Rect", left, top, right, bottom);
}
private:
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index 3209a53..57db816 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -178,9 +178,6 @@
virtual void resetShader() = 0;
virtual void setupShader(SkiaShader* shader) = 0;
- virtual void resetShadow() = 0;
- virtual void setupShadow(float radius, float dx, float dy, int color) = 0;
-
virtual void resetPaintFilter() = 0;
virtual void setupPaintFilter(int clearBits, int setBits) = 0;
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index d26ee38..6bfa203 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -27,9 +27,15 @@
// Constructors
///////////////////////////////////////////////////////////////////////////////
-Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0),
- invisible(false), empty(false), alpha(1.0f) {
-
+Snapshot::Snapshot()
+ : flags(0)
+ , previous(NULL)
+ , layer(NULL)
+ , fbo(0)
+ , invisible(false)
+ , empty(false)
+ , height(0)
+ , alpha(1.0f) {
transform = &mTransformRoot;
clipRect = &mClipRectRoot;
region = NULL;
@@ -40,10 +46,16 @@
* Copies the specified snapshot/ The specified snapshot is stored as
* the previous snapshot.
*/
-Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
- flags(0), previous(s), layer(s->layer), fbo(s->fbo),
- invisible(s->invisible), empty(false),
- viewport(s->viewport), height(s->height), alpha(s->alpha) {
+Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags)
+ : flags(0)
+ , previous(s)
+ , layer(s->layer)
+ , fbo(s->fbo)
+ , invisible(s->invisible)
+ , empty(false)
+ , viewport(s->viewport)
+ , height(s->height)
+ , alpha(s->alpha) {
if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
mTransformRoot.load(*s->transform);
diff --git a/libs/hwui/utils/Blur.cpp b/libs/hwui/utils/Blur.cpp
index 85d90d0..c020b40 100644
--- a/libs/hwui/utils/Blur.cpp
+++ b/libs/hwui/utils/Blur.cpp
@@ -23,6 +23,31 @@
namespace android {
namespace uirenderer {
+// This constant approximates the scaling done in the software path's
+// "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)).
+static const float BLUR_SIGMA_SCALE = 0.57735f;
+
+float Blur::convertRadiusToSigma(float radius) {
+ return radius > 0 ? BLUR_SIGMA_SCALE * radius + 0.5f : 0.0f;
+}
+
+float Blur::convertSigmaToRadius(float sigma) {
+ return sigma > 0.5f ? (sigma - 0.5f) / BLUR_SIGMA_SCALE : 0.0f;
+}
+
+/**
+ * HWUI has used a slightly different equation than Skia to generate the value
+ * for sigma and to preserve compatibility we have kept that logic.
+ *
+ * Based on some experimental radius and sigma values we approximate the
+ * equation sigma = f(radius) as sigma = radius * 0.3 + 0.6. The larger the
+ * radius gets, the more our gaussian blur will resemble a box blur since with
+ * large sigma the gaussian curve begins to lose its shape.
+ */
+static float legacyConvertRadiusToSigma(float radius) {
+ return radius > 0 ? 0.3f * radius + 0.6f : 0.0f;
+}
+
void Blur::generateGaussianWeights(float* weights, int32_t radius) {
// Compute gaussian weights for the blur
// e is the euler's number
@@ -31,13 +56,7 @@
// g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 )
// x is of the form [-radius .. 0 .. radius]
// and sigma varies with radius.
- // Based on some experimental radius values and sigma's
- // we approximately fit sigma = f(radius) as
- // sigma = radius * 0.3 + 0.6
- // The larger the radius gets, the more our gaussian blur
- // will resemble a box blur since with large sigma
- // the gaussian curve begins to lose its shape
- float sigma = 0.3f * (float) radius + 0.6f;
+ float sigma = legacyConvertRadiusToSigma((float) radius);
// Now compute the coefficints
// We will store some redundant values to save some math during
diff --git a/libs/hwui/utils/Blur.h b/libs/hwui/utils/Blur.h
index 6c176e9..79aff65 100644
--- a/libs/hwui/utils/Blur.h
+++ b/libs/hwui/utils/Blur.h
@@ -18,12 +18,18 @@
#define ANDROID_HWUI_BLUR_H
#include <stdint.h>
+#include <cutils/compiler.h>
namespace android {
namespace uirenderer {
class Blur {
public:
+ // If radius > 0, return the corresponding sigma, else return 0
+ ANDROID_API static float convertRadiusToSigma(float radius);
+ // If sigma > 0.6, return the corresponding radius, else return 0
+ ANDROID_API static float convertSigmaToRadius(float sigma);
+
static void generateGaussianWeights(float* weights, int32_t radius);
static void horizontal(float* weights, int32_t radius, const uint8_t* source,
uint8_t* dest, int32_t width, int32_t height);
diff --git a/libs/hwui/utils/GLUtils.cpp b/libs/hwui/utils/GLUtils.cpp
new file mode 100644
index 0000000..9b298ca
--- /dev/null
+++ b/libs/hwui/utils/GLUtils.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <utils/Log.h>
+
+#include "GLUtils.h"
+
+namespace android {
+namespace uirenderer {
+
+void GLUtils::dumpGLErrors() {
+ GLenum status = GL_NO_ERROR;
+ while ((status = glGetError()) != GL_NO_ERROR) {
+ switch (status) {
+ case GL_INVALID_ENUM:
+ ALOGE("GL error: GL_INVALID_ENUM");
+ break;
+ case GL_INVALID_VALUE:
+ ALOGE("GL error: GL_INVALID_VALUE");
+ break;
+ case GL_INVALID_OPERATION:
+ ALOGE("GL error: GL_INVALID_OPERATION");
+ break;
+ case GL_OUT_OF_MEMORY:
+ ALOGE("GL error: Out of memory!");
+ break;
+ default:
+ ALOGE("GL error: 0x%x", status);
+ }
+ }
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/utils/GLUtils.h b/libs/hwui/utils/GLUtils.h
new file mode 100644
index 0000000..890e374
--- /dev/null
+++ b/libs/hwui/utils/GLUtils.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef GLUTILS_H
+#define GLUTILS_H
+
+namespace android {
+namespace uirenderer {
+
+class GLUtils {
+private:
+public:
+ /**
+ * Print out any GL errors with ALOGE
+ */
+ static void dumpGLErrors();
+
+}; // class GLUtils
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* GLUTILS_H */
diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h
index 7deabe9..8ba44dc 100644
--- a/libs/hwui/utils/MathUtils.h
+++ b/libs/hwui/utils/MathUtils.h
@@ -38,4 +38,4 @@
} /* namespace uirenderer */
} /* namespace android */
-#endif /* RENDERNODE_H */
+#endif /* MATHUTILS_H */
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 0c8a823..724022b 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -149,6 +149,7 @@
private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 18;
private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 19;
private static final int MSG_UNLOAD_SOUND_EFFECTS = 20;
+ private static final int MSG_SYSTEM_READY = 21;
// start of messages handled under wakelock
// these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
// and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
@@ -370,7 +371,7 @@
private int mScoConnectionState;
// true if boot sequence has been completed
- private boolean mBootCompleted;
+ private boolean mSystemReady;
// listener for SoundPool sample load completion indication
private SoundPoolCallback mSoundPoolCallBack;
// thread for SoundPool listener
@@ -525,7 +526,6 @@
intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
intentFilter.addAction(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG);
intentFilter.addAction(Intent.ACTION_USB_AUDIO_DEVICE_PLUG);
- intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
@@ -559,6 +559,43 @@
}
+ public void systemReady() {
+ sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE,
+ 0, 0, null, 0);
+ }
+
+ public void onSystemReady() {
+ mSystemReady = true;
+ sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE,
+ 0, 0, null, 0);
+
+ mKeyguardManager =
+ (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+ mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR;
+ resetBluetoothSco();
+ getBluetoothHeadset();
+ //FIXME: this is to maintain compatibility with deprecated intent
+ // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
+ Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
+ newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
+ AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
+ sendStickyBroadcastToAll(newIntent);
+
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ if (adapter != null) {
+ adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
+ BluetoothProfile.A2DP);
+ }
+
+ sendMsg(mAudioHandler,
+ MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
+ SENDMSG_REPLACE,
+ 0,
+ 0,
+ null,
+ SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
+ }
+
private void createAudioSystemThread() {
mAudioSystemThread = new AudioSystemThread();
mAudioSystemThread.start();
@@ -1996,7 +2033,7 @@
/** @see AudioManager#startBluetoothSco() */
public void startBluetoothSco(IBinder cb, int targetSdkVersion){
if (!checkAudioSettingsPermission("startBluetoothSco()") ||
- !mBootCompleted) {
+ !mSystemReady) {
return;
}
ScoClient client = getScoClient(cb, true);
@@ -2013,7 +2050,7 @@
/** @see AudioManager#stopBluetoothSco() */
public void stopBluetoothSco(IBinder cb){
if (!checkAudioSettingsPermission("stopBluetoothSco()") ||
- !mBootCompleted) {
+ !mSystemReady) {
return;
}
ScoClient client = getScoClient(cb, false);
@@ -3277,7 +3314,7 @@
int status;
synchronized (mSoundEffectsLock) {
- if (!mBootCompleted) {
+ if (!mSystemReady) {
Log.w(TAG, "onLoadSoundEffects() called before boot complete");
return false;
}
@@ -3700,6 +3737,10 @@
case MSG_BROADCAST_BT_CONNECTION_STATE:
onBroadcastScoConnectionState(msg.arg1);
break;
+
+ case MSG_SYSTEM_READY:
+ onSystemReady();
+ break;
}
}
}
@@ -4169,36 +4210,6 @@
newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState);
sendStickyBroadcastToAll(newIntent);
}
- } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
- mBootCompleted = true;
- sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE,
- 0, 0, null, 0);
-
- mKeyguardManager =
- (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
- mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR;
- resetBluetoothSco();
- getBluetoothHeadset();
- //FIXME: this is to maintain compatibility with deprecated intent
- // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
- Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
- newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
- AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
- sendStickyBroadcastToAll(newIntent);
-
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- if (adapter != null) {
- adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
- BluetoothProfile.A2DP);
- }
-
- sendMsg(mAudioHandler,
- MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
- SENDMSG_REPLACE,
- 0,
- 0,
- null,
- SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
} else if (action.equals(Intent.ACTION_SCREEN_ON)) {
AudioSystem.setParameters("screen_state=on");
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 1899685..dab6eed 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -72,6 +72,7 @@
*
* AudioTrack is not final and thus permits subclasses, but such use is not recommended.
*/
+// add {@link #write(float[], int, int)} when @hide removed
public class AudioTrack
{
//---------------------------------------------------------
@@ -172,16 +173,14 @@
public @interface WriteMode {}
/**
- * @hide CANDIDATE FOR PUBLIC API
* The write mode indicating the write operation will block until all data has been written,
- * to be used in {@link #write(ByteBuffer, int, int, int)}.
+ * to be used in {@link #write(ByteBuffer, int, int)}
*/
public final static int WRITE_BLOCKING = 0;
/**
- * @hide CANDIDATE FOR PUBLIC API
* The write mode indicating the write operation will return immediately after
* queuing as much audio data for playback as possible without blocking, to be used in
- * {@link #write(ByteBuffer, int, int, int)}.
+ * {@link #write(ByteBuffer, int, int)}.
*/
public final static int WRITE_NON_BLOCKING = 1;
@@ -247,6 +246,7 @@
* @see AudioFormat#ENCODING_PCM_8BIT
* @see AudioFormat#ENCODING_PCM_16BIT
*/
+ // add @see AudioFormat#ENCODING_PCM_FLOAT when @hide removed
private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
/**
* Audio session ID
@@ -302,6 +302,7 @@
* @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
* @throws java.lang.IllegalArgumentException
*/
+ // add {@link AudioFormat#ENCODING_PCM_FLOAT} to audioFormat section above, when @hide removed
public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
int bufferSizeInBytes, int mode)
throws IllegalArgumentException {
@@ -343,6 +344,7 @@
* @param sessionId Id of audio session the AudioTrack must be attached to
* @throws java.lang.IllegalArgumentException
*/
+ // add {@link AudioFormat#ENCODING_PCM_FLOAT} to audioFormat section above, when @hide removed
public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
int bufferSizeInBytes, int mode, int sessionId)
throws IllegalArgumentException {
@@ -461,11 +463,14 @@
break;
case AudioFormat.ENCODING_PCM_16BIT:
case AudioFormat.ENCODING_PCM_8BIT:
+ case AudioFormat.ENCODING_PCM_FLOAT:
mAudioFormat = audioFormat;
break;
default:
throw new IllegalArgumentException("Unsupported sample encoding."
- + " Should be ENCODING_PCM_8BIT or ENCODING_PCM_16BIT.");
+ + " Should be ENCODING_PCM_8BIT or ENCODING_PCM_16BIT"
+ // + " or ENCODING_PCM_FLOAT" when @hide removed
+ + ".");
}
//--------------
@@ -730,6 +735,7 @@
* or {@link #ERROR} if unable to query for output properties,
* or the minimum buffer size expressed in bytes.
*/
+ // add {@link AudioFormat#ENCODING_PCM_FLOAT} to audioFormat section above, when @hide removed
static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) {
int channelCount = 0;
switch(channelConfig) {
@@ -752,7 +758,8 @@
}
if ((audioFormat != AudioFormat.ENCODING_PCM_16BIT)
- && (audioFormat != AudioFormat.ENCODING_PCM_8BIT)) {
+ && (audioFormat != AudioFormat.ENCODING_PCM_8BIT)
+ && (audioFormat != AudioFormat.ENCODING_PCM_FLOAT)) {
loge("getMinBufferSize(): Invalid audio format.");
return ERROR_BAD_VALUE;
}
@@ -1152,7 +1159,7 @@
public int write(byte[] audioData, int offsetInBytes, int sizeInBytes) {
- if (mState == STATE_UNINITIALIZED) {
+ if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
return ERROR_INVALID_OPERATION;
}
@@ -1190,13 +1197,13 @@
* starts.
* @param sizeInShorts the number of shorts to read in audioData after the offset.
* @return the number of shorts that were written or {@link #ERROR_INVALID_OPERATION}
- * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
- * the parameters don't resolve to valid data and indexes.
+ * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+ * the parameters don't resolve to valid data and indexes.
*/
public int write(short[] audioData, int offsetInShorts, int sizeInShorts) {
- if (mState == STATE_UNINITIALIZED) {
+ if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
return ERROR_INVALID_OPERATION;
}
@@ -1220,7 +1227,80 @@
/**
- * @hide CANDIDATE FOR PUBLIC API
+ * Writes the audio data to the audio sink for playback (streaming mode),
+ * or copies audio data for later playback (static buffer mode).
+ * In static buffer mode, copies the data to the buffer starting at offset 0,
+ * and the write mode is ignored.
+ * In streaming mode, the blocking behavior will depend on the write mode.
+ * <p>
+ * Note that the actual playback of this data might occur after this function
+ * returns. This function is thread safe with respect to {@link #stop} calls,
+ * in which case all of the specified data might not be written to the audio sink.
+ * <p>
+ * @param audioData the array that holds the data to play.
+ * The implementation does not clip for sample values within the nominal range
+ * [-1.0f, 1.0f], provided that all gains in the audio pipeline are
+ * less than or equal to unity (1.0f), and in the absence of post-processing effects
+ * that could add energy, such as reverb. For the convenience of applications
+ * that compute samples using filters with non-unity gain,
+ * sample values +3 dB beyond the nominal range are permitted.
+ * However such values may eventually be limited or clipped, depending on various gains
+ * and later processing in the audio path. Therefore applications are encouraged
+ * to provide samples values within the nominal range.
+ * @param offsetInFloats the offset, expressed as a number of floats,
+ * in audioData where the data to play starts.
+ * @param sizeInFloats the number of floats to read in audioData after the offset.
+ * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
+ * effect in static mode.
+ * <BR>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
+ * to the audio sink.
+ * <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
+ * queuing as much audio data for playback as possible without blocking.
+ * @return the number of floats that were written, or {@link #ERROR_INVALID_OPERATION}
+ * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+ * the parameters don't resolve to valid data and indexes.
+ * @hide candidate for public API
+ */
+ public int write(float[] audioData, int offsetInFloats, int sizeInFloats,
+ @WriteMode int writeMode) {
+
+ if (mState == STATE_UNINITIALIZED) {
+ Log.e(TAG, "AudioTrack.write() called in invalid state STATE_UNINITIALIZED");
+ return ERROR_INVALID_OPERATION;
+ }
+
+ if (mAudioFormat != AudioFormat.ENCODING_PCM_FLOAT) {
+ Log.e(TAG, "AudioTrack.write(float[] ...) requires format ENCODING_PCM_FLOAT");
+ return ERROR_INVALID_OPERATION;
+ }
+
+ if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) {
+ Log.e(TAG, "AudioTrack.write() called with invalid blocking mode");
+ return ERROR_BAD_VALUE;
+ }
+
+ if ( (audioData == null) || (offsetInFloats < 0 ) || (sizeInFloats < 0)
+ || (offsetInFloats + sizeInFloats < 0) // detect integer overflow
+ || (offsetInFloats + sizeInFloats > audioData.length)) {
+ Log.e(TAG, "AudioTrack.write() called with invalid array, offset, or size");
+ return ERROR_BAD_VALUE;
+ }
+
+ int ret = native_write_float(audioData, offsetInFloats, sizeInFloats, mAudioFormat,
+ writeMode == WRITE_BLOCKING);
+
+ if ((mDataLoadMode == MODE_STATIC)
+ && (mState == STATE_NO_STATIC_DATA)
+ && (ret > 0)) {
+ // benign race with respect to other APIs that read mState
+ mState = STATE_INITIALIZED;
+ }
+
+ return ret;
+ }
+
+
+ /**
* Writes the audio data to the audio sink for playback (streaming mode),
* or copies audio data for later playback (static buffer mode).
* In static buffer mode, copies the data to the buffer starting at its 0 offset, and the write
@@ -1250,6 +1330,11 @@
return ERROR_INVALID_OPERATION;
}
+ if (mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
+ Log.e(TAG, "AudioTrack.write(ByteBuffer ...) not yet supported for ENCODING_PCM_FLOAT");
+ return ERROR_INVALID_OPERATION;
+ }
+
if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) {
Log.e(TAG, "AudioTrack.write() called with invalid blocking mode");
return ERROR_BAD_VALUE;
@@ -1490,6 +1575,10 @@
private native final int native_write_short(short[] audioData,
int offsetInShorts, int sizeInShorts, int format);
+ private native final int native_write_float(float[] audioData,
+ int offsetInFloats, int sizeInFloats, int format,
+ boolean isBlocking);
+
private native final int native_write_native_bytes(Object audioData,
int positionInBytes, int sizeInBytes, int format, boolean blocking);
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index ed98b96..90fe695 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -66,8 +66,6 @@
LOCAL_CFLAGS +=
-LOCAL_LDLIBS := -lpthread
-
LOCAL_MODULE:= libmedia_jni
include $(BUILD_SHARED_LIBRARY)
diff --git a/packages/SystemUI/res/layout/heads_up.xml b/packages/SystemUI/res/layout/heads_up.xml
index e4954e7..7d9cfa1 100644
--- a/packages/SystemUI/res/layout/heads_up.xml
+++ b/packages/SystemUI/res/layout/heads_up.xml
@@ -20,7 +20,7 @@
<com.android.systemui.statusbar.policy.HeadsUpNotificationView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
- android:layout_width="@dimen/notification_panel_width"
+ android:layout_width="match_parent"
android:id="@+id/content_holder"
android:background="@drawable/notification_panel_bg"
/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 3267c36..372bde2 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -22,7 +22,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
android:id="@+id/notification_panel"
- android:layout_width="0dp"
+ android:layout_width="match_parent"
android:layout_height="match_parent"
>
@@ -61,7 +61,7 @@
<com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
android:id="@+id/notification_container_parent"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
android:clipToPadding="false"
android:clipChildren="false">
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index f9b022c..c29da18 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -35,9 +35,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include layout="@layout/status_bar_expanded"
- android:layout_width="@dimen/notification_panel_width"
- android:layout_height="match_parent"
- android:layout_gravity="start|top" />
+ style="@style/StatusBarExpanded" />
</com.android.systemui.statusbar.phone.PanelHolder>
</com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index d8a3114..8ec48c8 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Onlangse programme"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Deursoek"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knoppie vir wissel van invoermetode."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Versoenbaarheid-zoem se knoppie."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoem kleiner na groter skerm."</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 9d1e036..7aaaaf3 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"የቅርብ ጊዜ መተግበሪያዎች"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"ፈልግ"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"ካሜራ"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"የግቤት ስልት አዝራር ቀይር"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"የተኳኋኝአጉላ አዝራር።"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"አነስተኛውን ማያ ወደ ትልቅ አጉላ።"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 22a032a..1c06615 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"التطبيقات الحديثة"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"بحث"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"الكاميرا"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"الهاتف"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"زر تبديل طريقة الإدخال."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"زر تكبير/تصغير للتوافق."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"استخدام التكبير/التصغير لتحويل شاشة صغيرة إلى شاشة أكبر"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 00ac707..febcab6 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Скорошни приложения"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Търсене"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Камера"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Бутон за превключване на метода на въвеждане."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Бутон за промяна на мащаба с цел съвместимост."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Промяна на мащаба на екрана от по-малък до по-голям."</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index bfad5bc..658ece0 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Aplicacions recents"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Cerca"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Càmera"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botó de canvi del mètode d\'entrada."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botó de zoom de compatibilitat."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Amplia menys com més gran sigui la pantalla."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 94ba5c7..c7d2703 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Nové aplikace"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Hledat"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Fotoaparát"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tlačítko přepnutí metody zadávání"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tlačítko úpravy velikosti z důvodu kompatibility"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zvětšit menší obrázek na větší obrazovku."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index df442ab..c740051 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Seneste apps"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Søg"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Telefon"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Skift indtastningsmetode-knappen."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knap for kompatibilitetszoom."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom mindre til større skærm."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 451476c..40ecc49 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Kürzlich geöffnete Apps"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Suchen"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Telefonnummer"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Schaltfläche zum Ändern der Eingabemethode"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Schaltfläche für Kompatibilitätszoom"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom auf einen größeren Bildschirm"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 6dcffcf..0e98ce0 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Πρόσφατες εφαρμογές"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Αναζήτηση"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Φωτογραφική μηχανή"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Τηλέφωνο"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Κουμπί εναλλαγής μεθόδου εισόδου"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Κουμπί εστίασης συμβατότητας."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Ζουμ από μικρότερη σε μεγαλύτερη οθόνη."</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 91a334a..f4098b7 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Recent apps"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Search"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Camera"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Phone"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Switch input method button."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 91a334a..f4098b7 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Recent apps"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Search"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Camera"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Phone"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Switch input method button."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 2150cbe..51198e6 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Aplicaciones recientes"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Buscar"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Cámara"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botón Cambiar método de entrada"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidad"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de pantalla más pequeña a más grande"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 3424166..1b73e18 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Aplicaciones recientes"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Buscar"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Cámara"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Teléfono"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botón Cambiar método de entrada"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidad"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de pantalla más pequeña a más grande"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 8dbf9af..0f95c60 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Hiljutised rakendused"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Otsing"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kaamera"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Sisestusmeetodi vahetamise nupp."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Sobivussuumi nupp."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Suumi suuremale ekraanile vähem."</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index b2ac990..f36d04b 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"برنامههای اخیر"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"جستجو"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"دوربین"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"کلید تغییر روش ورود متن."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"دکمه بزرگنمایی سازگار."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"بزرگنمایی از صفحههای کوچک تا بزرگ."</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index af0df4d..4ae3851 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Viimeaikaiset sovellukset"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Haku"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Syöttötavan vaihtopainike."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Yhteensopivuuszoomaus-painike."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoomaa pienemmältä suuremmalle ruudulle."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index f01c99a..c55a5fc 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Applications récentes"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Rechercher"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Appareil photo"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bouton \"Changer le mode de saisie\""</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Bouton \"Zoom de compatibilité\""</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de compatibilité avec la taille de l\'écran"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 5efbd2f..1121918 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Applications récentes"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Rechercher"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Appareil photo"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bouton \"Changer le mode de saisie\""</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Bouton \"Zoom de compatibilité\""</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de compatibilité avec la taille de l\'écran"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index e6d38ef..f9e6aad 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"हाल ही के ऐप्स"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"खोजें"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"कैमरा"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"फ़ोन"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट पद्धति बटन स्विच करें."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"संगतता ज़ूम बटन."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"छोटी से बड़ी स्क्रीन पर ज़ूम करें."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index b777b8f..435f701 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Nedavne aplikacije"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Pretraži"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Fotoaparat"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Telefon"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Gumb za promjenu načina unosa."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Gumb za kompatibilnost zumiranja."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zumiranje manjeg zaslona na veći."</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 10732fe..7685477 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Legújabb alkalmazás"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Keresés"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Telefon"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Beviteli mód váltása gomb."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kompatibilitási zoom gomb."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kicsinyítsen a nagyobb képernyőhöz."</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index f1c4869..7a8ab10 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Վերջին ծրագրերը"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Որոնել"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Ֆոտոխցիկ"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Միացնել մուտքագրման եղանակի կոճակը:"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Համատեղելիության խոշորացման կոճակը:"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Դիտափոխել փոքրից ավելի մեծ էկրան:"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index f0b0713..cdb0816 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Apl terbaru"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Telusuri"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Telepon"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tombol beralih metode masukan."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tombol perbesar/perkecil kompatibilitas."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Perbesar dari layar kecil ke besar."</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 6a57682..401dbce 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Applicazioni recenti"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Cerca"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Fotocamera"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Telefono"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Pulsante per cambiare metodo di immissione."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Pulsante zoom compatibilità."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom inferiore per schermo più grande."</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 3e87b76..08ffc54 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"אפליקציות אחרונות"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"חפש"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"מצלמה"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"לחצן החלפת שיטת קלט."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"לחצן מרחק מתצוגה של תאימות."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"שנה מרחק מתצוגה של מסך קטן לגדול יותר."</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 1edb630..2caa069 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"最近使ったアプリ"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"検索"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"カメラ"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"入力方法の切り替えボタン。"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"互換ズームボタン。"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"小さい画面から大きい画面に拡大。"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 9d4344a..62e40d0 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"ბოლოს გამოყენებული აპები"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"ძიება"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"კამერა"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"შეყვანის მეთოდის გადართვის ღილაკი."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"თავსებადი მასშტაბირების ღილაკი."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"შეცვალეთ პატარა ეკრანი უფრო დიდით."</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index bb2d3b9..35a6917 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"កម្មវិធីថ្មីៗ"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"ស្វែងរក"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"ម៉ាស៊ីនថត"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ប្ដូរប៊ូតុងវិធីសាស្ត្របញ្ចូល។"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ប៊ូតុងពង្រីកត្រូវគ្នា។"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ពង្រីក/បង្រួមអេក្រង់ពីទៅធំ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 83ffa9f..d7cd13b 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"최근에 사용한 앱"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"검색"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"카메라"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"입력 방법 버튼을 전환합니다."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"호환성 확대/축소 버튼입니다."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"작은 화면을 큰 화면으로 확대합니다."</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 9a3d483..991fb66 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"ແອັບຯຫຼ້າສຸດ"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"ຊອກຫາ"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"ກ້ອງ"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"ໂທລະສັບ"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ປຸ່ມສະລັບຮູບແບບການປ້ອນຂໍ້ມູນ."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ປຸ່ມຊູມທີ່ໃຊ້ຮ່ວມກັນໄດ້."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ຊູມຈໍນ້ອຍໄປເປັນຈໍຂະຫນາດໃຫຍ່."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 379cfce..87087b4 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Naujausios programos"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Ieškoti"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Fotoaparatas"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Telefonas"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Perjungti įvesties metodo mygtuką."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Suderinamumo priartinimo mygtukas."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Padidinti ekraną."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index ca07095..04571e7 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Nesen izmantotās lietotnes"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Meklēt"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Tālruņa numurs"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Ievades metodes maiņas poga."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Saderības tālummaiņas poga."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Veikt tālummaiņu no mazāka ekrāna uz lielāku."</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 4545301..3e7b660 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Сүүлийн апп"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Хайх"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Камер"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Оруулах аргыг сэлгэх товч."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Тохиромжтой өсгөх товч."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Жижгээс том дэлгэцрүү өсгөх."</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 587b84f..af50786 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Aplikasi terbaharu"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Cari"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Butang tukar kaedah input."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Butang zum keserasian."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Skrin zum lebih kecil kepada lebih besar."</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 001e733..9fa68b9 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Nylige apper"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Søk"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Telefonnummer"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bytt knapp for inndatametode."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Zoomknapp for kompatibilitet."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom fra mindre til større skjerm."</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 8a6e33b..8cf16bf 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Recente apps"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Zoeken"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Camera"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Telefoon"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knop voor wijzigen invoermethode."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knop voor compatibiliteitszoom."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kleiner scherm uitzoomen naar groter scherm."</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 4862d1b..e51341d 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Ostatnie aplikacje"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Szukaj"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Aparat"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Przycisk przełączania metody wprowadzania."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Przycisk powiększenia na potrzeby zgodności."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Powiększa mniejszy ekran do większego."</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 012283a..11843b6 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Aplicações recentes"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Pesquisar"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Câmara"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Telemóvel"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Alternar botão de método de introdução."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botão zoom de compatibilidade."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom menor para ecrã maior."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 0978d18..162d763 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Aplicativos recentes"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Pesquisar"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Câmera"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Alterar botão do método de entrada."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botão de zoom da compatibilidade."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Aumentar a tela com zoom."</string>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 25f643f..9f82651 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -126,6 +126,8 @@
<skip />
<!-- no translation found for accessibility_camera_button (8064671582820358152) -->
<skip />
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
<skip />
<!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 5c9764a..75ba35b 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Aplicaţii recente"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Căutați"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Cameră foto"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Buton pentru comutarea metodei de introducere."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Buton zoom pentru compatibilitate."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Faceţi zoom de la o imagine mai mică la una mai mare."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 976a793..6bdc6f4 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Недавние приложения"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Поиск"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Камера"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Кнопка переключения способа ввода."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Кнопка масштабирования (режим совместимости)"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Уменьшение изображения для увеличения свободного места на экране."</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 1224c3a..12c90ec 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Nové aplikácie"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Hľadať"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Fotoaparát"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tlačidlo prepnutia metódy vstupu."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tlačidlo úpravy veľkosti z dôvodu kompatibility."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zväčšiť menší obrázok na väčšiu obrazovku."</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 10011bc..48d7727 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Nedavni programi"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Iskanje"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Fotoaparat"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Telefon"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Gumb za preklop načina vnosa."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Gumb povečave za združljivost."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Povečava manjšega na večji zaslon."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 0c6a939..dba27a1 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Недавне апликације"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Претражите"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Камера"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Телефон"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Дугме Промени метод уноса."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Дугме Зум компатибилности."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Зумирање са мањег на већи екран."</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index d8bd1b1..0d58ed3 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Senaste apparna"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Sök"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Mobil"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knapp för byte av inmatningsmetod."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knapp för kompatibilitetszoom."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zooma mindre skärm till större."</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index d308b518..b626f78 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -76,6 +76,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Programu za hivi karibuni"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Tafuta"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Swichi kitufe cha mbinu ingizi."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kichupo cha kukuza kwa utangamanifu"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kuza kidogo kwa skrini kubwa."</string>
diff --git a/packages/SystemUI/res/values-sw600dp/styles.xml b/packages/SystemUI/res/values-sw600dp/styles.xml
index b7becac..1ea9442 100644
--- a/packages/SystemUI/res/values-sw600dp/styles.xml
+++ b/packages/SystemUI/res/values-sw600dp/styles.xml
@@ -18,4 +18,10 @@
<style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer">
<item name="android:layout_width">480dp</item>
</style>
+
+ <style name="StatusBarExpanded">
+ <item name="android:layout_width">@dimen/notification_panel_width</item>
+ <item name="android:layout_height">match_parent</item>
+ <item name="android:layout_gravity">start|top</item>
+ </style>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 7929a30..6cb4a48 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"แอปพลิเคชันล่าสุด"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"ค้นหา"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"กล้องถ่ายรูป"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ปุ่มสลับวิธีการป้อนข้อมูล"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ปุ่มซูมที่ใช้งานร่วมกันได้"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ซูมหน้าจอให้มีขนาดใหญ่ขึ้น"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 92473a4..17e720e 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Kamakailang apps"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Hanapin"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Camera"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Ilipat ang button na pamamaraan ng pag-input."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Button ng zoom ng pagiging tugma."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Mag-zoom nang mas maliit sa mas malaking screen."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 9837ff8..1bf033f5 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Son uygulamalar"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Ara"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Giriş yöntemini değiştirme düğmesi."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Uyumluluk zum düğmesi."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Daha büyük ekrana daha küçük yakınlaştır."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 534f520..a5284ae 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Останні програми"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Пошук"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Камера"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Номер телефону"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Кнопка перемикання методу введення."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Кнопка масштабування сумісності."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Збільшення екрана."</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 56fc89c..8df2449 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Ứng dụng gần đây"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Tìm kiếm"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Máy ảnh"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Nút chuyển phương thức nhập."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Nút thu phóng khả năng tương thích."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Thu phóng màn hình lớn hơn hoặc nhỏ hơn."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 442fdb7..8643ca8 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"最近运行的应用"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"搜索"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"相机"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"输入法切换按钮。"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"兼容性缩放按钮。"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"将小屏幕的图片放大在较大屏幕上显示。"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 54a3b1e..9d93094 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"最近使用的應用程式"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"搜尋"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"相機"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"電話"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"切換輸入法按鈕。"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"相容性縮放按鈕。"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"將較小螢幕的畫面放大在較大螢幕上顯示。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index fc74f53..07b7841 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -78,6 +78,8 @@
<string name="accessibility_recent" msgid="8571350598987952883">"最近使用的應用程式"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"搜尋"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"相機"</string>
+ <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+ <skip />
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"切換輸入法按鈕。"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"相容性縮放按鈕。"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"將較小螢幕的畫面放大在較大螢幕上顯示。"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index dfe8838..48a1ace 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -78,6 +78,7 @@
<string name="accessibility_recent" msgid="8571350598987952883">"Izinhlelo zokusebenza zakamuva"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Sesha"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Ikhamela"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"Ifoni"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Vula indlela yokungena yenkinobho"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Inkinobho evumelekile yokusondeza"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Sondeza kancane esikrinini esikhudlwana"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 93a75bc..c0376f0 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -118,6 +118,8 @@
<integer name="recents_animate_task_bar_exit_duration">150</integer>
<!-- The animation duration for animating in the info pane. -->
<integer name="recents_animate_task_view_info_pane_duration">150</integer>
+ <!-- The animation duration for animating the removal of a task view. -->
+ <integer name="recents_animate_task_view_remove_duration">150</integer>
<!-- The minimum alpha for the dim applied to cards that go deeper into the stack. -->
<integer name="recents_max_task_stack_view_dim">96</integer>
<!-- Transposes the search bar layout in landscape -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 8d3a565..b6e6ee2 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -196,9 +196,6 @@
<!-- Quick Settings CA Cert Warning tile geometry: gap between icon and text -->
<dimen name="qs_cawarn_tile_margin_below_icon">3dp</dimen>
- <!-- The width of the notification panel window: match_parent below sw600dp -->
- <dimen name="notification_panel_width">-1dp</dimen>
-
<!-- used by DessertCase -->
<dimen name="dessert_case_cell_size">192dp</dimen>
@@ -223,6 +220,9 @@
<!-- The translation in the Z index for each task above the last task. -->
<dimen name="recents_task_view_z_increment">5dp</dimen>
+ <!-- The amount to translate when animating the removal of a task. -->
+ <dimen name="recents_task_view_remove_anim_translation_x">75dp</dimen>
+
<!-- The amount of space a user has to scroll to dismiss any info panes. -->
<dimen name="recents_task_stack_scroll_dismiss_info_pane_distance">50dp</dimen>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 4369741..6418930 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -28,5 +28,11 @@
<item type="id" name="alpha_animator_end_value_tag"/>
<item type="id" name="top_inset_animator_end_value_tag"/>
<item type="id" name="height_animator_end_value_tag"/>
+ <item type="id" name="translation_y_animator_start_value_tag"/>
+ <item type="id" name="translation_z_animator_start_value_tag"/>
+ <item type="id" name="scale_animator_start_value_tag"/>
+ <item type="id" name="alpha_animator_start_value_tag"/>
+ <item type="id" name="top_inset_animator_start_value_tag"/>
+ <item type="id" name="height_animator_start_value_tag"/>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 8ab646d..6608c5d 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -171,4 +171,10 @@
<style name="systemui_theme" parent="@android:style/Theme.DeviceDefault" />
+ <style name="StatusBarExpanded">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">match_parent</item>
+ <item name="android:layout_gravity">start|top</item>
+ </style>
+
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 3be6932..b74f6ac 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -22,6 +22,7 @@
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -37,6 +38,7 @@
import com.android.systemui.recents.views.RecentsView;
import java.util.ArrayList;
+import java.util.Set;
/** Our special app widget host */
class RecentsAppWidgetHost extends AppWidgetHost {
@@ -60,7 +62,7 @@
/* Activity */
public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks,
- RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks{
+ RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks {
FrameLayout mContainerView;
RecentsView mRecentsView;
View mEmptyView;
@@ -308,6 +310,9 @@
filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(mScreenOffReceiver, filter);
+
+ // Register any broadcast receivers for the task loader
+ RecentsTaskLoader.getInstance().registerReceivers(this, mRecentsView);
}
@Override
@@ -320,6 +325,7 @@
// Unregister any broadcast receivers we have registered
unregisterReceiver(mServiceBroadcastReceiver);
unregisterReceiver(mScreenOffReceiver);
+ RecentsTaskLoader.getInstance().unregisterReceivers();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index cb7e42a..463cf74 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -49,6 +49,8 @@
public int taskStackScrollDismissInfoPaneDistance;
public int taskStackMaxDim;
public int taskViewInfoPaneAnimDuration;
+ public int taskViewRemoveAnimDuration;
+ public int taskViewRemoveAnimTranslationXPx;
public int taskViewTranslationZMinPx;
public int taskViewTranslationZIncrementPx;
public int taskViewRoundedCornerRadiusPx;
@@ -108,6 +110,10 @@
taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim);
taskViewInfoPaneAnimDuration =
res.getInteger(R.integer.recents_animate_task_view_info_pane_duration);
+ taskViewRemoveAnimDuration =
+ res.getInteger(R.integer.recents_animate_task_view_remove_duration);
+ taskViewRemoveAnimTranslationXPx =
+ res.getDimensionPixelSize(R.dimen.recents_task_view_remove_anim_translation_x);
taskViewRoundedCornerRadiusPx =
res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
taskViewTranslationZMinPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java
new file mode 100644
index 0000000..4e620b6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents;
+
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Looper;
+import com.android.internal.content.PackageMonitor;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * The package monitor listens for changes from PackageManager to update the contents of the Recents
+ * list.
+ */
+public class RecentsPackageMonitor extends PackageMonitor {
+ public interface PackageCallbacks {
+ public void onComponentRemoved(Set<ComponentName> cns);
+ }
+
+ PackageCallbacks mCb;
+ List<ActivityManager.RecentTaskInfo> mTasks;
+ SystemServicesProxy mSsp;
+
+ public RecentsPackageMonitor(Context context) {
+ mSsp = new SystemServicesProxy(context);
+ }
+
+ /** Registers the broadcast receivers with the specified callbacks. */
+ public void register(Context context, PackageCallbacks cb) {
+ mCb = cb;
+ register(context, Looper.getMainLooper(), false);
+ }
+
+ /** Unregisters the broadcast receivers. */
+ @Override
+ public void unregister() {
+ super.unregister();
+ mTasks.clear();
+ }
+
+ /** Sets the list of tasks to match against package broadcast changes. */
+ void setTasks(List<ActivityManager.RecentTaskInfo> tasks) {
+ mTasks = tasks;
+ }
+
+ @Override
+ public void onPackageRemoved(String packageName, int uid) {
+ if (mCb == null) return;
+
+ // Identify all the tasks that should be removed as a result of the package being removed.
+ // Using a set to ensure that we callback once per unique component.
+ HashSet<ComponentName> componentsToRemove = new HashSet<ComponentName>();
+ for (ActivityManager.RecentTaskInfo t : mTasks) {
+ ComponentName cn = t.baseIntent.getComponent();
+ if (cn.getPackageName().equals(packageName)) {
+ componentsToRemove.add(cn);
+ }
+ }
+ // Notify our callbacks that the components no longer exist
+ mCb.onComponentRemoved(componentsToRemove);
+ }
+
+ @Override
+ public boolean onPackageChanged(String packageName, int uid, String[] components) {
+ onPackageModified(packageName);
+ return true;
+ }
+
+ @Override
+ public void onPackageModified(String packageName) {
+ if (mCb == null) return;
+
+ // Identify all the tasks that should be removed as a result of the package being removed.
+ // Using a set to ensure that we callback once per unique component.
+ HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>();
+ HashSet<ComponentName> componentsToRemove = new HashSet<ComponentName>();
+ for (ActivityManager.RecentTaskInfo t : mTasks) {
+ ComponentName cn = t.baseIntent.getComponent();
+ if (cn.getPackageName().equals(packageName)) {
+ if (componentsKnownToExist.contains(cn)) {
+ // If we know that the component still exists in the package, then skip
+ continue;
+ }
+ if (mSsp.getActivityInfo(cn) != null) {
+ componentsKnownToExist.add(cn);
+ } else {
+ componentsToRemove.add(cn);
+ }
+ }
+ }
+ // Notify our callbacks that the components no longer exist
+ mCb.onComponentRemoved(componentsToRemove);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index c9038ee..c64ca54 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -300,6 +300,8 @@
TaskResourceLoadQueue mLoadQueue;
TaskResourceLoader mLoader;
+ RecentsPackageMonitor mPackageMonitor;
+
int mMaxThumbnailCacheSize;
int mMaxIconCacheSize;
@@ -325,6 +327,7 @@
// Initialize the proxy, cache and loaders
mSystemServicesProxy = new SystemServicesProxy(context);
+ mPackageMonitor = new RecentsPackageMonitor(context);
mLoadQueue = new TaskResourceLoadQueue();
mApplicationIconCache = new DrawableLruCache(iconCacheSize);
mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
@@ -510,6 +513,9 @@
mLoadQueue.addTask(t, true);
}
+ // Update the package monitor with the list of packages to listen for
+ mPackageMonitor.setTasks(tasks);
+
return root;
}
@@ -548,14 +554,16 @@
}
/** Completely removes the resource data from the pool. */
- public void deleteTaskData(Task t) {
+ public void deleteTaskData(Task t, boolean notifyTaskDataUnloaded) {
Console.log(Constants.Log.App.TaskDataLoader,
"[RecentsTaskLoader|deleteTask]", t);
mLoadQueue.removeTask(t);
mThumbnailCache.remove(t.key);
mApplicationIconCache.remove(t.key);
- t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon);
+ if (notifyTaskDataUnloaded) {
+ t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon);
+ }
}
/** Stops the task loader and clears all pending tasks */
@@ -565,6 +573,21 @@
mLoadQueue.clearTasks();
}
+ /** Registers any broadcast receivers. */
+ public void registerReceivers(Context context, RecentsPackageMonitor.PackageCallbacks cb) {
+ // Register the broadcast receiver to handle messages related to packages being added/removed
+ mPackageMonitor.register(context, cb);
+ }
+
+ /** Unregisters any broadcast receivers. */
+ public void unregisterReceivers() {
+ mPackageMonitor.unregister();
+ }
+
+ /**
+ * Handles signals from the system, trimming memory when requested to prevent us from running
+ * out of memory.
+ */
void onTrimMemory(int level) {
Console.log(Constants.Log.App.Memory, "[RecentsTaskLoader|onTrimMemory]",
Console.trimMemoryLevelToString(level));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index b41555f..0d3ee38 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -165,11 +165,12 @@
}
/** Removes the task and kills the process */
- public void removeTask(int taskId) {
+ public void removeTask(int taskId, boolean isDocument) {
if (mAm == null) return;
if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
- mAm.removeTask(taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
+ // Remove the task, and only kill the process if it is not a document
+ mAm.removeTask(taskId, isDocument ? 0 : ActivityManager.REMOVE_TASK_KILL_PROCESS);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index eb7b5c6..a6d7e67 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -19,6 +19,7 @@
import android.app.ActivityOptions;
import android.app.TaskStackBuilder;
import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
@@ -33,19 +34,22 @@
import com.android.systemui.recents.Console;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.RecentsPackageMonitor;
import com.android.systemui.recents.RecentsTaskLoader;
import com.android.systemui.recents.model.SpaceNode;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
+import java.util.Set;
/**
* This view is the the top level layout that contains TaskStacks (which are laid out according
* to their SpaceNode bounds.
*/
-public class RecentsView extends FrameLayout implements TaskStackView.TaskStackViewCallbacks {
+public class RecentsView extends FrameLayout implements TaskStackView.TaskStackViewCallbacks,
+ RecentsPackageMonitor.PackageCallbacks {
/** The RecentsView callbacks */
public interface RecentsViewCallbacks {
@@ -342,7 +346,7 @@
RecentsTaskLoader.getInstance().getSystemServicesProxy()
.moveTaskToFront(task.key.id, opts);
} else {
- // Launch the activity with the desired animation
+ // Launch the activity anew with the desired animation
Intent i = new Intent(task.key.baseIntent);
i.setFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
| Intent.FLAG_ACTIVITY_TASK_ON_HOME
@@ -357,6 +361,9 @@
} catch (ActivityNotFoundException anfe) {
Console.logError(getContext(), "Could not start Activity");
}
+
+ // And clean up the old task
+ onTaskRemoved(task);
}
Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
@@ -385,4 +392,35 @@
TaskStackBuilder.create(getContext())
.addNextIntentWithParentStack(intent).startActivities();
}
+
+ @Override
+ public void onTaskRemoved(Task t) {
+ // Remove any stored data from the loader. We currently don't bother notifying the views
+ // that the data has been unloaded because at the point we call onTaskRemoved(), the views
+ // either don't need to be updated, or have already been removed.
+ RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+ loader.deleteTaskData(t, false);
+
+ // Remove the old task from activity manager
+ int flags = t.key.baseIntent.getFlags();
+ boolean isDocument = (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) ==
+ Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
+ RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(t.key.id,
+ isDocument);
+ }
+
+ /**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
+
+ @Override
+ public void onComponentRemoved(Set<ComponentName> cns) {
+ // Propagate this event down to each task stack view
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ if (child instanceof TaskStackView) {
+ TaskStackView stackView = (TaskStackView) child;
+ stackView.onComponentRemoved(cns);
+ }
+ }
+ }
}
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 cfacd18..55c38a9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -21,7 +21,9 @@
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.Region;
@@ -39,6 +41,7 @@
import com.android.systemui.recents.Console;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.RecentsPackageMonitor;
import com.android.systemui.recents.RecentsTaskLoader;
import com.android.systemui.recents.Utilities;
import com.android.systemui.recents.model.Task;
@@ -46,17 +49,19 @@
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Set;
/* The visual representation of a task stack view */
public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCallbacks,
TaskView.TaskViewCallbacks, ViewPool.ViewPoolConsumer<TaskView, Task>,
- View.OnClickListener, View.OnLongClickListener {
+ View.OnClickListener, View.OnLongClickListener, RecentsPackageMonitor.PackageCallbacks {
/** The TaskView callbacks */
interface TaskStackViewCallbacks {
public void onTaskLaunched(TaskStackView stackView, TaskView tv, TaskStack stack, Task t);
public void onTaskAppInfoLaunched(Task t);
+ public void onTaskRemoved(Task t);
}
TaskStack mStack;
@@ -705,9 +710,24 @@
}
}
+ // Update the min/max scroll and animate other task views into their new positions
updateMinMaxScroll(true);
int movement = (int) (Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height());
requestSynchronizeStackViewsWithModel(Utilities.calculateTranslationAnimationDuration(movement));
+
+ // If there are no remaining tasks, then either unfilter the current stack, or just close
+ // the activity if there are no filtered stacks
+ if (mStack.getTaskCount() == 0) {
+ boolean shouldFinishActivity = true;
+ if (mStack.hasFilteredTasks()) {
+ mStack.unfilterTasks();
+ shouldFinishActivity = (mStack.getTaskCount() == 0);
+ }
+ if (shouldFinishActivity) {
+ Activity activity = (Activity) getContext();
+ activity.finish();
+ }
+ }
}
/**
@@ -1070,6 +1090,32 @@
tv.showInfoPane(new Rect(0, 0, 0, (int) overlapHeight));
return true;
}
+
+ /**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
+
+ @Override
+ public void onComponentRemoved(Set<ComponentName> cns) {
+ // For other tasks, just remove them directly if they no longer exist
+ ArrayList<Task> tasks = mStack.getTasks();
+ for (int i = tasks.size() - 1; i >= 0; i--) {
+ final Task t = tasks.get(i);
+ if (cns.contains(t.key.baseIntent.getComponent())) {
+ TaskView tv = getChildViewForTask(t);
+ if (tv != null) {
+ // For visible children, defer removing the task until after the animation
+ tv.animateRemoval(new Runnable() {
+ @Override
+ public void run() {
+ mStack.removeTask(t);
+ }
+ });
+ } else {
+ // Otherwise, remove the task from the stack immediately
+ mStack.removeTask(t);
+ }
+ }
+ }
+ }
}
/* Handles touch events */
@@ -1432,30 +1478,12 @@
public void onChildDismissed(View v) {
TaskView tv = (TaskView) v;
Task task = tv.getTask();
- Activity activity = (Activity) mSv.getContext();
// Remove the task from the view
mSv.mStack.removeTask(task);
- // Remove any stored data from the loader
- RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
- loader.deleteTaskData(task);
-
- // Remove the task from activity manager
- RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(tv.getTask().key.id);
-
- // If there are no remaining tasks, then either unfilter the current stack, or just close
- // the activity if there are no filtered stacks
- if (mSv.mStack.getTaskCount() == 0) {
- boolean shouldFinishActivity = true;
- if (mSv.mStack.hasFilteredTasks()) {
- mSv.mStack.unfilterTasks();
- shouldFinishActivity = (mSv.mStack.getTaskCount() == 0);
- }
- if (shouldFinishActivity) {
- activity.finish();
- }
- }
+ // Notify the callback that we've removed the task and it can clean up after it
+ mSv.mCb.onTaskRemoved(task);
// Disable HW layers
mSv.decHwLayersRefCount("swipeComplete");
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 45c2fae..b03f389 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -246,6 +246,24 @@
.start();
}
+ /** Animates the deletion of this task view */
+ public void animateRemoval(final Runnable r) {
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ animate().translationX(config.taskViewRemoveAnimTranslationXPx)
+ .alpha(0f)
+ .setStartDelay(0)
+ .setInterpolator(BakedBezierInterpolator.INSTANCE)
+ .setDuration(config.taskViewRemoveAnimDuration)
+ .withLayer()
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ post(r);
+ }
+ })
+ .start();
+ }
+
/** Returns the rect we want to clip (it may not be the full rect) */
Rect getClippingRect(Rect outRect) {
getHitRect(outRect);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index ecefc39..898f06e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1029,6 +1029,9 @@
}
protected void addNotificationViews(NotificationData.Entry entry) {
+ if (entry == null) {
+ return;
+ }
// Add the expanded view and icon.
int pos = mNotificationData.add(entry);
if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index e24ddd9..48c54fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -73,8 +73,7 @@
public void show(Bundle options) {
mShowing = true;
mStatusBarWindowManager.setKeyguardShowing(true);
- showBouncerOrKeyguard();
- updateStates();
+ reset();
}
/**
@@ -95,7 +94,9 @@
}
private void showBouncer() {
- mBouncer.show();
+ if (!mOccluded) {
+ mBouncer.show();
+ }
updateStates();
}
@@ -103,8 +104,15 @@
* Reset the state of the view.
*/
public void reset() {
- showBouncerOrKeyguard();
- updateStates();
+ if (mShowing) {
+ if (mOccluded) {
+ mPhoneStatusBar.hideKeyguard();
+ mBouncer.hide();
+ } else {
+ showBouncerOrKeyguard();
+ }
+ updateStates();
+ }
}
public void onScreenTurnedOff() {
@@ -147,7 +155,7 @@
public void setOccluded(boolean occluded) {
mOccluded = occluded;
mStatusBarWindowManager.setKeyguardOccluded(occluded);
- updateStates();
+ reset();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index a4c9df5..c2061f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -79,8 +79,9 @@
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
PixelFormat.TRANSLUCENT);
+ mLp.width = ViewGroup.LayoutParams.MATCH_PARENT;
mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
- mLp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
+ mLp.gravity = Gravity.TOP;
mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
mLp.setTitle("StatusBar");
mLp.packageName = mContext.getPackageName();
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 c952698..ca383aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -54,6 +54,12 @@
private static final int TAG_END_ALPHA = R.id.alpha_animator_end_value_tag;
private static final int TAG_END_HEIGHT = R.id.height_animator_end_value_tag;
private static final int TAG_END_TOP_INSET = R.id.top_inset_animator_end_value_tag;
+ private static final int TAG_START_TRANSLATION_Y = R.id.translation_y_animator_start_value_tag;
+ private static final int TAG_START_TRANSLATION_Z = R.id.translation_z_animator_start_value_tag;
+ private static final int TAG_START_SCALE = R.id.scale_animator_start_value_tag;
+ private static final int TAG_START_ALPHA = R.id.alpha_animator_start_value_tag;
+ private static final int TAG_START_HEIGHT = R.id.height_animator_start_value_tag;
+ private static final int TAG_START_TOP_INSET = R.id.top_inset_animator_start_value_tag;
private final Interpolator mFastOutSlowInInterpolator;
public NotificationStackScrollLayout mHostLayout;
@@ -139,23 +145,34 @@
private void startHeightAnimation(final ExpandableView child,
StackScrollState.ViewState viewState) {
+ Integer previousStartValue = getChildTag(child, TAG_START_HEIGHT);
Integer previousEndValue = getChildTag(child, TAG_END_HEIGHT);
- if (previousEndValue != null && previousEndValue == viewState.height) {
+ int newEndValue = viewState.height;
+ if (previousEndValue != null && previousEndValue == newEndValue) {
return;
}
ValueAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_HEIGHT);
- long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator,
- mAnimationFilter.animateHeight);
- if (newDuration <= 0) {
- // no new animation needed, let's just apply the value
- child.setActualHeight(viewState.height, false /* notifyListeners */);
- if (previousAnimator != null && !isRunning()) {
- onAnimationFinished();
+ if (!mAnimationFilter.animateHeight) {
+ // just a local update was performed
+ if (previousAnimator != null) {
+ // we need to increase all animation keyframes of the previous animator by the
+ // relative change to the end value
+ PropertyValuesHolder[] values = previousAnimator.getValues();
+ int relativeDiff = newEndValue - previousEndValue;
+ int newStartValue = previousStartValue + relativeDiff;
+ values[0].setIntValues(newStartValue, newEndValue);
+ child.setTag(TAG_START_HEIGHT, newStartValue);
+ child.setTag(TAG_END_HEIGHT, newEndValue);
+ previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+ return;
+ } else {
+ // no new animation needed, let's just apply the value
+ child.setActualHeight(newEndValue, false);
+ return;
}
- return;
}
- ValueAnimator animator = ValueAnimator.ofInt(child.getActualHeight(), viewState.height);
+ ValueAnimator animator = ValueAnimator.ofInt(child.getActualHeight(), newEndValue);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
@@ -164,6 +181,7 @@
}
});
animator.setInterpolator(mFastOutSlowInInterpolator);
+ long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator);
animator.setDuration(newDuration);
animator.addListener(getGlobalAnimationFinishedListener());
// remove the tag when the animation is finished
@@ -171,38 +189,49 @@
@Override
public void onAnimationEnd(Animator animation) {
child.setTag(TAG_ANIMATOR_HEIGHT, null);
+ child.setTag(TAG_START_HEIGHT, null);
child.setTag(TAG_END_HEIGHT, null);
}
});
startInstantly(animator);
child.setTag(TAG_ANIMATOR_HEIGHT, animator);
- child.setTag(TAG_END_HEIGHT, viewState.height);
+ child.setTag(TAG_START_HEIGHT, child.getActualHeight());
+ child.setTag(TAG_END_HEIGHT, newEndValue);
}
private void startAlphaAnimation(final ExpandableView child,
final StackScrollState.ViewState viewState) {
- final float endAlpha = viewState.alpha;
+ Float previousStartValue = getChildTag(child,TAG_START_ALPHA);
Float previousEndValue = getChildTag(child,TAG_END_ALPHA);
- if (previousEndValue != null && previousEndValue == endAlpha) {
+ final float newEndValue = viewState.alpha;
+ if (previousEndValue != null && previousEndValue == newEndValue) {
return;
}
ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_ALPHA);
- long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator,
- mAnimationFilter.animateAlpha);
- if (newDuration <= 0) {
- // no new animation needed, let's just apply the value
- child.setAlpha(endAlpha);
- if (endAlpha == 0) {
- child.setVisibility(View.INVISIBLE);
+ if (!mAnimationFilter.animateAlpha) {
+ // just a local update was performed
+ if (previousAnimator != null) {
+ // we need to increase all animation keyframes of the previous animator by the
+ // relative change to the end value
+ PropertyValuesHolder[] values = previousAnimator.getValues();
+ float relativeDiff = newEndValue - previousEndValue;
+ float newStartValue = previousStartValue + relativeDiff;
+ values[0].setFloatValues(newStartValue, newEndValue);
+ child.setTag(TAG_START_ALPHA, newStartValue);
+ child.setTag(TAG_END_ALPHA, newEndValue);
+ previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+ return;
+ } else {
+ // no new animation needed, let's just apply the value
+ child.setAlpha(newEndValue);
+ if (newEndValue == 0) {
+ child.setVisibility(View.INVISIBLE);
+ }
}
- if (previousAnimator != null && !isRunning()) {
- onAnimationFinished();
- }
- return;
}
ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.ALPHA,
- child.getAlpha(), endAlpha);
+ child.getAlpha(), newEndValue);
animator.setInterpolator(mFastOutSlowInInterpolator);
// Handle layer type
final int currentLayerType = child.getLayerType();
@@ -213,10 +242,11 @@
@Override
public void onAnimationEnd(Animator animation) {
child.setLayerType(currentLayerType, null);
- if (endAlpha == 0 && !mWasCancelled) {
+ if (newEndValue == 0 && !mWasCancelled) {
child.setVisibility(View.INVISIBLE);
}
child.setTag(TAG_ANIMATOR_ALPHA, null);
+ child.setTag(TAG_START_ALPHA, null);
child.setTag(TAG_END_ALPHA, null);
}
@@ -230,6 +260,7 @@
mWasCancelled = false;
}
});
+ long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator);
animator.setDuration(newDuration);
animator.addListener(getGlobalAnimationFinishedListener());
// remove the tag when the animation is finished
@@ -241,31 +272,42 @@
});
startInstantly(animator);
child.setTag(TAG_ANIMATOR_ALPHA, animator);
- child.setTag(TAG_END_ALPHA, endAlpha);
+ child.setTag(TAG_START_ALPHA, child.getAlpha());
+ child.setTag(TAG_END_ALPHA, newEndValue);
}
private void startZTranslationAnimation(final ExpandableView child,
final StackScrollState.ViewState viewState) {
+ Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_Z);
Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Z);
- if (previousEndValue != null && previousEndValue == viewState.zTranslation) {
+ float newEndValue = viewState.zTranslation;
+ if (previousEndValue != null && previousEndValue == newEndValue) {
return;
}
ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TRANSLATION_Z);
- long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator,
- mAnimationFilter.animateZ);
- if (newDuration <= 0) {
- // no new animation needed, let's just apply the value
- child.setTranslationZ(viewState.zTranslation);
-
- if (previousAnimator != null && !isRunning()) {
- onAnimationFinished();
+ if (!mAnimationFilter.animateZ) {
+ // just a local update was performed
+ if (previousAnimator != null) {
+ // we need to increase all animation keyframes of the previous animator by the
+ // relative change to the end value
+ PropertyValuesHolder[] values = previousAnimator.getValues();
+ float relativeDiff = newEndValue - previousEndValue;
+ float newStartValue = previousStartValue + relativeDiff;
+ values[0].setFloatValues(newStartValue, newEndValue);
+ child.setTag(TAG_START_TRANSLATION_Z, newStartValue);
+ child.setTag(TAG_END_TRANSLATION_Z, newEndValue);
+ previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+ return;
+ } else {
+ // no new animation needed, let's just apply the value
+ child.setTranslationZ(newEndValue);
}
- return;
}
ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.TRANSLATION_Z,
- child.getTranslationZ(), viewState.zTranslation);
+ child.getTranslationZ(), newEndValue);
animator.setInterpolator(mFastOutSlowInInterpolator);
+ long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator);
animator.setDuration(newDuration);
animator.addListener(getGlobalAnimationFinishedListener());
// remove the tag when the animation is finished
@@ -273,35 +315,49 @@
@Override
public void onAnimationEnd(Animator animation) {
child.setTag(TAG_ANIMATOR_TRANSLATION_Z, null);
+ child.setTag(TAG_START_TRANSLATION_Z, null);
child.setTag(TAG_END_TRANSLATION_Z, null);
}
});
startInstantly(animator);
child.setTag(TAG_ANIMATOR_TRANSLATION_Z, animator);
- child.setTag(TAG_END_TRANSLATION_Z, viewState.zTranslation);
+ child.setTag(TAG_START_TRANSLATION_Z, child.getTranslationZ());
+ child.setTag(TAG_END_TRANSLATION_Z, newEndValue);
}
private void startYTranslationAnimation(final ExpandableView child,
StackScrollState.ViewState viewState) {
+ Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_Y);
Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Y);
- if (previousEndValue != null && previousEndValue == viewState.yTranslation) {
+ float newEndValue = viewState.yTranslation;
+ if (previousEndValue != null && previousEndValue == newEndValue) {
return;
}
ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TRANSLATION_Y);
- long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator,
- mAnimationFilter.animateY);
- if (newDuration <= 0) {
- // no new animation needed, let's just apply the value
- child.setTranslationY(viewState.yTranslation);
- if (previousAnimator != null && !isRunning()) {
- onAnimationFinished();
+ if (!mAnimationFilter.animateY) {
+ // just a local update was performed
+ if (previousAnimator != null) {
+ // we need to increase all animation keyframes of the previous animator by the
+ // relative change to the end value
+ PropertyValuesHolder[] values = previousAnimator.getValues();
+ float relativeDiff = newEndValue - previousEndValue;
+ float newStartValue = previousStartValue + relativeDiff;
+ values[0].setFloatValues(newStartValue, newEndValue);
+ child.setTag(TAG_START_TRANSLATION_Y, newStartValue);
+ child.setTag(TAG_END_TRANSLATION_Y, newEndValue);
+ previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+ return;
+ } else {
+ // no new animation needed, let's just apply the value
+ child.setTranslationY(newEndValue);
+ return;
}
- return;
}
ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.TRANSLATION_Y,
- child.getTranslationY(), viewState.yTranslation);
+ child.getTranslationY(), newEndValue);
animator.setInterpolator(mFastOutSlowInInterpolator);
+ long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator);
animator.setDuration(newDuration);
animator.addListener(getGlobalAnimationFinishedListener());
// remove the tag when the animation is finished
@@ -309,39 +365,53 @@
@Override
public void onAnimationEnd(Animator animation) {
child.setTag(TAG_ANIMATOR_TRANSLATION_Y, null);
+ child.setTag(TAG_START_TRANSLATION_Y, null);
child.setTag(TAG_END_TRANSLATION_Y, null);
}
});
startInstantly(animator);
child.setTag(TAG_ANIMATOR_TRANSLATION_Y, animator);
- child.setTag(TAG_END_TRANSLATION_Y, viewState.yTranslation);
+ child.setTag(TAG_START_TRANSLATION_Y, child.getTranslationY());
+ child.setTag(TAG_END_TRANSLATION_Y, newEndValue);
}
private void startScaleAnimation(final ExpandableView child,
StackScrollState.ViewState viewState) {
+ Float previousStartValue = getChildTag(child, TAG_START_SCALE);
Float previousEndValue = getChildTag(child, TAG_END_SCALE);
- if (previousEndValue != null && previousEndValue == viewState.scale) {
+ float newEndValue = viewState.scale;
+ if (previousEndValue != null && previousEndValue == newEndValue) {
return;
}
ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_SCALE);
- long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator,
- mAnimationFilter.animateScale);
- if (newDuration <= 0) {
- // no new animation needed, let's just apply the value
- child.setScaleX(viewState.scale);
- child.setScaleY(viewState.scale);
- if (previousAnimator != null && !isRunning()) {
- onAnimationFinished();
+ if (!mAnimationFilter.animateScale) {
+ // just a local update was performed
+ if (previousAnimator != null) {
+ // we need to increase all animation keyframes of the previous animator by the
+ // relative change to the end value
+ PropertyValuesHolder[] values = previousAnimator.getValues();
+ float relativeDiff = newEndValue - previousEndValue;
+ float newStartValue = previousStartValue + relativeDiff;
+ values[0].setFloatValues(newStartValue, newEndValue);
+ values[1].setFloatValues(newStartValue, newEndValue);
+ child.setTag(TAG_START_SCALE, newStartValue);
+ child.setTag(TAG_END_SCALE, newEndValue);
+ previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+ return;
+ } else {
+ // no new animation needed, let's just apply the value
+ child.setScaleX(newEndValue);
+ child.setScaleY(newEndValue);
}
- return;
}
PropertyValuesHolder holderX =
- PropertyValuesHolder.ofFloat(View.SCALE_X, child.getScaleX(), viewState.scale);
+ PropertyValuesHolder.ofFloat(View.SCALE_X, child.getScaleX(), newEndValue);
PropertyValuesHolder holderY =
- PropertyValuesHolder.ofFloat(View.SCALE_Y, child.getScaleY(), viewState.scale);
+ PropertyValuesHolder.ofFloat(View.SCALE_Y, child.getScaleY(), newEndValue);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(child, holderX, holderY);
animator.setInterpolator(mFastOutSlowInInterpolator);
+ long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator);
animator.setDuration(newDuration);
animator.addListener(getGlobalAnimationFinishedListener());
// remove the tag when the animation is finished
@@ -349,12 +419,14 @@
@Override
public void onAnimationEnd(Animator animation) {
child.setTag(TAG_ANIMATOR_SCALE, null);
+ child.setTag(TAG_START_SCALE, null);
child.setTag(TAG_END_SCALE, null);
}
});
startInstantly(animator);
child.setTag(TAG_ANIMATOR_SCALE, animator);
- child.setTag(TAG_END_SCALE, viewState.scale);
+ child.setTag(TAG_START_SCALE, child.getScaleX());
+ child.setTag(TAG_END_SCALE, newEndValue);
}
/**
@@ -408,23 +480,16 @@
* Cancel the previous animator and get the duration of the new animation.
*
* @param previousAnimator the animator which was running before
- * @param newAnimationNeeded indicating whether a new animation should be started for this
- * property
* @return the new duration
*/
- private long cancelAnimatorAndGetNewDuration(ValueAnimator previousAnimator,
- boolean newAnimationNeeded) {
+ private long cancelAnimatorAndGetNewDuration(ValueAnimator previousAnimator) {
long newDuration = mCurrentLength;
if (previousAnimator != null) {
- if (!newAnimationNeeded) {
- // This is only an update, no new event came in. lets just take the remaining
- // duration as the new duration
- newDuration = previousAnimator.getDuration()
- - previousAnimator.getCurrentPlayTime();
- }
+ // We take either the desired length of the new animation or the remaining time of
+ // the previous animator, whichever is longer.
+ newDuration = Math.max(previousAnimator.getDuration()
+ - previousAnimator.getCurrentPlayTime(), newDuration);
previousAnimator.cancel();
- } else if (!newAnimationNeeded){
- newDuration = 0;
}
return newDuration;
}
diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk
index 07933b4..f1ddc07 100644
--- a/rs/jni/Android.mk
+++ b/rs/jni/Android.mk
@@ -27,7 +27,6 @@
LOCAL_CFLAGS += -Wno-unused-parameter
-LOCAL_LDLIBS := -lpthread
LOCAL_ADDITIONAL_DEPENDENCIES := $(addprefix $(rs_generated_include_dir)/,rsgApiFuncDecl.h)
LOCAL_MODULE:= librs_jni
LOCAL_ADDITIONAL_DEPENDENCIES += $(rs_generated_source)
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 3619112..4a59a8f 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -38,6 +38,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.graphics.Point;
import android.graphics.Rect;
@@ -197,6 +198,8 @@
private final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
+ private final UserManager mUserManager;
+
private int mCurrentUserId = UserHandle.USER_OWNER;
private final LongArray mTempLongArray = new LongArray();
@@ -210,15 +213,6 @@
return getUserStateLocked(mCurrentUserId);
}
- private UserState getUserStateLocked(int userId) {
- UserState state = mUserStates.get(userId);
- if (state == null) {
- state = new UserState(userId);
- mUserStates.put(userId, state);
- }
- return state;
- }
-
/**
* Creates a new instance.
*
@@ -228,6 +222,7 @@
mContext = context;
mPackageManager = mContext.getPackageManager();
mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
+ mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mSecurityPolicy = new SecurityPolicy();
mMainHandler = new MainHandler(mContext.getMainLooper());
registerBroadcastReceivers();
@@ -235,11 +230,22 @@
context.getContentResolver());
}
+ private UserState getUserStateLocked(int userId) {
+ UserState state = mUserStates.get(userId);
+ if (state == null) {
+ state = new UserState(userId);
+ mUserStates.put(userId, state);
+ }
+ return state;
+ }
+
private void registerBroadcastReceivers() {
PackageMonitor monitor = new PackageMonitor() {
@Override
public void onSomePackagesChanged() {
synchronized (mLock) {
+ // Only the profile parent can install accessibility services.
+ // Therefore we ignore packages from linked profiles.
if (getChangingUserId() != mCurrentUserId) {
return;
}
@@ -262,6 +268,8 @@
public void onPackageRemoved(String packageName, int uid) {
synchronized (mLock) {
final int userId = getChangingUserId();
+ // Only the profile parent can install accessibility services.
+ // Therefore we ignore packages from linked profiles.
if (userId != mCurrentUserId) {
return;
}
@@ -297,6 +305,8 @@
int uid, boolean doit) {
synchronized (mLock) {
final int userId = getChangingUserId();
+ // Only the profile parent can install accessibility services.
+ // Therefore we ignore packages from linked profiles.
if (userId != mCurrentUserId) {
return false;
}
@@ -359,6 +369,9 @@
@Override
public int addClient(IAccessibilityManagerClient client, int userId) {
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
// If the client is from a process that runs across users such as
@@ -388,6 +401,9 @@
@Override
public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) {
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution..
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
// This method does nothing for a background user.
@@ -414,6 +430,9 @@
@Override
public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) {
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
// The automation service is a fake one and should not be reported
@@ -435,6 +454,9 @@
int userId) {
List<AccessibilityServiceInfo> result = null;
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
@@ -468,6 +490,9 @@
public void interrupt(int userId) {
CopyOnWriteArrayList<Service> services;
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
// This method does nothing for a background user.
@@ -491,6 +516,9 @@
public int addAccessibilityInteractionConnection(IWindow windowToken,
IAccessibilityInteractionConnection connection, int userId) throws RemoteException {
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
final int windowId = sNextWindowId++;
@@ -527,6 +555,9 @@
@Override
public void removeAccessibilityInteractionConnection(IWindow window) {
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
UserHandle.getCallingUserId());
IBinder token = window.asBinder();
@@ -675,6 +706,9 @@
Manifest.permission.RETRIEVE_WINDOW_TOKEN,
GET_WINDOW_TOKEN);
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(
UserHandle.getCallingUserId());
@@ -770,7 +804,7 @@
}
// Disconnect from services for the old user.
- UserState oldUserState = getUserStateLocked(mCurrentUserId);
+ UserState oldUserState = getCurrentUserStateLocked();
oldUserState.onSwitchToAnotherUser();
// Disable the local managers for the old user.
@@ -2034,6 +2068,9 @@
@Override
public List<AccessibilityWindowInfo> getWindows() {
synchronized (mLock) {
+ // We treat calls from a profile as if made by its perent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(
UserHandle.getCallingUserId());
@@ -2062,6 +2099,9 @@
@Override
public AccessibilityWindowInfo getWindow(int windowId) {
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(
UserHandle.getCallingUserId());
@@ -2092,6 +2132,9 @@
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(
UserHandle.getCallingUserId());
@@ -2136,9 +2179,12 @@
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(
- UserHandle.getCallingUserId());
+ UserHandle.getCallingUserId());
if (resolvedUserId != mCurrentUserId) {
return false;
}
@@ -2180,9 +2226,12 @@
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(
- UserHandle.getCallingUserId());
+ UserHandle.getCallingUserId());
if (resolvedUserId != mCurrentUserId) {
return false;
}
@@ -2224,9 +2273,12 @@
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(
- UserHandle.getCallingUserId());
+ UserHandle.getCallingUserId());
if (resolvedUserId != mCurrentUserId) {
return false;
}
@@ -2268,9 +2320,12 @@
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(
- UserHandle.getCallingUserId());
+ UserHandle.getCallingUserId());
if (resolvedUserId != mCurrentUserId) {
return false;
}
@@ -2311,9 +2366,12 @@
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(
- UserHandle.getCallingUserId());
+ UserHandle.getCallingUserId());
if (resolvedUserId != mCurrentUserId) {
return false;
}
@@ -2346,9 +2404,12 @@
public boolean performGlobalAction(int action) {
synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(
- UserHandle.getCallingUserId());
+ UserHandle.getCallingUserId());
if (resolvedUserId != mCurrentUserId) {
return false;
}
@@ -3407,16 +3468,35 @@
& AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0;
}
+ private int resolveProfileParentLocked(int userId) {
+ if (userId != mCurrentUserId) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ UserInfo parent = mUserManager.getProfileParent(userId);
+ if (parent != null) {
+ return parent.getUserHandle().getIdentifier();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ return userId;
+ }
+
public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) {
final int callingUid = Binder.getCallingUid();
if (callingUid == 0
|| callingUid == Process.SYSTEM_UID
|| callingUid == Process.SHELL_UID) {
- return mCurrentUserId;
+ if (userId == UserHandle.USER_CURRENT
+ || userId == UserHandle.USER_CURRENT_OR_SELF) {
+ return mCurrentUserId;
+ }
+ return resolveProfileParentLocked(userId);
}
final int callingUserId = UserHandle.getUserId(callingUid);
if (callingUserId == userId) {
- return userId;
+ return resolveProfileParentLocked(userId);
}
if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS)
&& !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) {
@@ -3673,8 +3753,10 @@
public void onChange(boolean selfChange, Uri uri) {
if (mAccessibilityEnabledUri.equals(uri)) {
synchronized (mLock) {
- // We will update when the automation service dies.
+ // Profiles share the accessibility state of the parent. Therefore,
+ // we are checking for changes only the parent settings.
UserState userState = getCurrentUserStateLocked();
+ // We will update when the automation service dies.
if (userState.mUiAutomationService == null) {
if (readAccessibilityEnabledSettingLocked(userState)) {
onUserStateChangedLocked(userState);
@@ -3683,8 +3765,10 @@
}
} else if (mTouchExplorationEnabledUri.equals(uri)) {
synchronized (mLock) {
- // We will update when the automation service dies.
+ // Profiles share the accessibility state of the parent. Therefore,
+ // we are checking for changes only the parent settings.
UserState userState = getCurrentUserStateLocked();
+ // We will update when the automation service dies.
if (userState.mUiAutomationService == null) {
if (readTouchExplorationEnabledSettingLocked(userState)) {
onUserStateChangedLocked(userState);
@@ -3693,8 +3777,10 @@
}
} else if (mDisplayMagnificationEnabledUri.equals(uri)) {
synchronized (mLock) {
- // We will update when the automation service dies.
+ // Profiles share the accessibility state of the parent. Therefore,
+ // we are checking for changes only the parent settings.
UserState userState = getCurrentUserStateLocked();
+ // We will update when the automation service dies.
if (userState.mUiAutomationService == null) {
if (readDisplayMagnificationEnabledSettingLocked(userState)) {
onUserStateChangedLocked(userState);
@@ -3703,8 +3789,10 @@
}
} else if (mEnabledAccessibilityServicesUri.equals(uri)) {
synchronized (mLock) {
- // We will update when the automation service dies.
+ // Profiles share the accessibility state of the parent. Therefore,
+ // we are checking for changes only the parent settings.
UserState userState = getCurrentUserStateLocked();
+ // We will update when the automation service dies.
if (userState.mUiAutomationService == null) {
if (readEnabledAccessibilityServicesLocked(userState)) {
onUserStateChangedLocked(userState);
@@ -3713,8 +3801,10 @@
}
} else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
synchronized (mLock) {
- // We will update when the automation service dies.
+ // Profiles share the accessibility state of the parent. Therefore,
+ // we are checking for changes only the parent settings.
UserState userState = getCurrentUserStateLocked();
+ // We will update when the automation service dies.
if (userState.mUiAutomationService == null) {
if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) {
onUserStateChangedLocked(userState);
@@ -3723,8 +3813,10 @@
}
} else if (mEnhancedWebAccessibilityUri.equals(uri)) {
synchronized (mLock) {
- // We will update when the automation service dies.
+ // Profiles share the accessibility state of the parent. Therefore,
+ // we are checking for changes only the parent settings.
UserState userState = getCurrentUserStateLocked();
+ // We will update when the automation service dies.
if (userState.mUiAutomationService == null) {
if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) {
onUserStateChangedLocked(userState);
@@ -3739,8 +3831,10 @@
|| mDisplayInversionUri.equals(uri)
|| mDisplayDaltonizerUri.equals(uri)) {
synchronized (mLock) {
- // We will update when the automation service dies.
+ // Profiles share the accessibility state of the parent. Therefore,
+ // we are checking for changes only the parent settings.
UserState userState = getCurrentUserStateLocked();
+ // We will update when the automation service dies.
if (userState.mUiAutomationService == null) {
if (readDisplayColorAdjustmentSettingsLocked(userState)) {
updateDisplayColorAdjustmentSettingsLocked(userState);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index ea03eb7..dfffa8a 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3517,6 +3517,18 @@
if (DBG) log("Invalid proxy properties, ignoring: " + proxy.toString());
return;
}
+
+ // This call could be coming from the PacManager, containing the port of the local
+ // proxy. If this new proxy matches the global proxy then copy this proxy to the
+ // global (to get the correct local port), and send a broadcast.
+ // TODO: Switch PacManager to have its own message to send back rather than
+ // reusing EVENT_HAS_CHANGED_PROXY and this call to handleApplyDefaultProxy.
+ if ((mGlobalProxy != null) && (proxy != null) && (proxy.getPacFileUrl() != null)
+ && proxy.getPacFileUrl().equals(mGlobalProxy.getPacFileUrl())) {
+ mGlobalProxy = proxy;
+ sendProxyBroadcast(mGlobalProxy);
+ return;
+ }
mDefaultProxy = proxy;
if (mGlobalProxy != null) return;
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 132ca00..ea9de1e 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -41,6 +41,7 @@
import android.provider.Settings.SettingNotFoundException;
import android.util.Slog;
import android.view.InputDevice;
+import android.media.AudioManager;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
@@ -73,6 +74,8 @@
private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators
private int mCurVibUid = -1;
+ private boolean mLowPowerMode;
+ private SettingsObserver mSettingObserver;
native static boolean vibratorExists();
native static void vibratorOn(long milliseconds);
@@ -159,15 +162,15 @@
public void systemReady() {
mIm = (InputManager)mContext.getSystemService(Context.INPUT_SERVICE);
+ mSettingObserver = new SettingsObserver(mH);
mContext.getContentResolver().registerContentObserver(
- Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), true,
- new ContentObserver(mH) {
- @Override
- public void onChange(boolean selfChange) {
- updateInputDeviceVibrators();
- }
- }, UserHandle.USER_ALL);
+ Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES),
+ true, mSettingObserver, UserHandle.USER_ALL);
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE), false,
+ mSettingObserver, UserHandle.USER_ALL);
mContext.registerReceiver(new BroadcastReceiver() {
@Override
@@ -179,6 +182,17 @@
updateInputDeviceVibrators();
}
+ private final class SettingsObserver extends ContentObserver {
+ public SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean SelfChange) {
+ updateInputDeviceVibrators();
+ }
+ }
+
public boolean hasVibrator() {
return doVibratorExists();
}
@@ -346,6 +360,9 @@
// Lock held on mVibrations
private void startVibrationLocked(final Vibration vib) {
try {
+ if (mLowPowerMode && vib.mStreamHint != AudioManager.STREAM_RING)
+ return;
+
int mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE,
vib.mStreamHint, vib.mUid, vib.mOpPkg);
if (mode == AppOpsManager.MODE_ALLOWED) {
@@ -425,6 +442,9 @@
} catch (SettingNotFoundException snfe) {
}
+ mLowPowerMode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.LOW_POWER_MODE, 0) != 0;
+
if (mVibrateInputDevicesSetting) {
if (!mInputDeviceListenerRegistered) {
mInputDeviceListenerRegistered = true;
diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
index 50cfe48..c32beda 100644
--- a/services/core/java/com/android/server/WiredAccessoryManager.java
+++ b/services/core/java/com/android/server/WiredAccessoryManager.java
@@ -70,6 +70,7 @@
private static final String NAME_HDMI = "hdmi";
private static final int MSG_NEW_DEVICE_STATE = 1;
+ private static final int MSG_SYSTEM_READY = 2;
private final Object mLock = new Object();
@@ -96,19 +97,9 @@
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
mObserver = new WiredAccessoryObserver();
-
- IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
- filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- context.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context ctx, Intent intent) {
- bootCompleted();
- }
- },
- filter, null, null);
}
- private void bootCompleted() {
+ private void onSystemReady() {
if (mUseDevInputEventForAudioJack) {
int switchValues = 0;
if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_HEADPHONE_INSERT) == 1) {
@@ -159,6 +150,16 @@
}
}
+ @Override
+ public void systemReady() {
+ synchronized (mLock) {
+ mWakeLock.acquire();
+
+ Message msg = mHandler.obtainMessage(MSG_SYSTEM_READY, 0, 0, null);
+ mHandler.sendMessage(msg);
+ }
+ }
+
/**
* Compare the existing headset state with the new state and pass along accordingly. Note
* that this only supports a single headset at a time. Inserting both a usb and jacked headset
@@ -220,6 +221,11 @@
case MSG_NEW_DEVICE_STATE:
setDevicesState(msg.arg1, msg.arg2, (String)msg.obj);
mWakeLock.release();
+ break;
+ case MSG_SYSTEM_READY:
+ onSystemReady();
+ mWakeLock.release();
+ break;
}
}
};
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3834c7e..9f6dd0b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1852,6 +1852,12 @@
@Override
public boolean onPackageChanged(String packageName, int uid, String[] components) {
+ onPackageModified(packageName);
+ return true;
+ }
+
+ @Override
+ public void onPackageModified(String packageName) {
final PackageManager pm = mContext.getPackageManager();
final ArrayList<Pair<Intent, Integer>> recentTaskIntents =
new ArrayList<Pair<Intent, Integer>>();
@@ -1887,7 +1893,6 @@
removeTaskByIdLocked(tasksToRemove.get(i), 0);
}
}
- return true;
}
@Override
@@ -9567,6 +9572,7 @@
}
mAppOpsService.systemReady();
+ mUsageStatsService.systemReady();
mSystemReady = true;
}
@@ -14388,6 +14394,7 @@
newConfig.seq = mConfigurationSeq;
mConfiguration = newConfig;
Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + newConfig);
+ mUsageStatsService.noteStartConfig(newConfig);
final Configuration configCopy = new Configuration(mConfiguration);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index a95710b..442da31 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1080,20 +1080,6 @@
}
}
- /**
- * Version of ensureActivitiesVisible that can easily be called anywhere.
- */
- final boolean ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
- return ensureActivitiesVisibleLocked(starting, configChanges, false);
- }
-
- final boolean ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
- boolean forceHomeShown) {
- ActivityRecord r = topRunningActivityLocked(null);
- return r != null &&
- ensureActivitiesVisibleLocked(r, starting, null, configChanges, forceHomeShown);
- }
-
// Checks if any of the stacks above this one has a fullscreen activity behind it.
// If so, this stack is hidden, otherwise it is visible.
private boolean isStackVisible() {
@@ -1105,16 +1091,26 @@
return true;
}
- // Start at the task above this one and go up, looking for a visible
- // fullscreen activity, or a translucent activity that requested the
- // wallpaper to be shown behind it.
+ /**
+ * Start at the task above this one and go up, looking for a visible
+ * fullscreen activity, or a translucent activity that requested the
+ * wallpaper to be shown behind it.
+ */
for (int i = mStacks.indexOf(this) + 1; i < mStacks.size(); i++) {
final ArrayList<TaskRecord> tasks = mStacks.get(i).getAllTasks();
for (int taskNdx = 0; taskNdx < tasks.size(); taskNdx++) {
final ArrayList<ActivityRecord> activities = tasks.get(taskNdx).mActivities;
for (int activityNdx = 0; activityNdx < activities.size(); activityNdx++) {
final ActivityRecord r = activities.get(activityNdx);
- if (!r.finishing && r.visible && r.fullscreen) {
+
+ // Conditions for an activity to obscure the stack we're
+ // examining:
+ // 1. Not Finishing AND Visible AND:
+ // 2. Either:
+ // - Full Screen Activity OR
+ // - On top of Home and our stack is NOT home
+ if (!r.finishing && r.visible && (r.fullscreen ||
+ (!isHomeStack() && r.frontOfTask && tasks.get(taskNdx).mOnTopOfHome))) {
return false;
}
}
@@ -1124,12 +1120,19 @@
return true;
}
+ final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
+ ActivityRecord r = topRunningActivityLocked(null);
+ if (r != null) {
+ ensureActivitiesVisibleLocked(r, starting, null, configChanges);
+ }
+ }
+
/**
* Make sure that all activities that need to be visible (that is, they
* currently can be seen by the user) actually are.
*/
- final boolean ensureActivitiesVisibleLocked(ActivityRecord top, ActivityRecord starting,
- String onlyThisProcess, int configChanges, boolean forceHomeShown) {
+ final void ensureActivitiesVisibleLocked(ActivityRecord top, ActivityRecord starting,
+ String onlyThisProcess, int configChanges) {
if (DEBUG_VISBILITY) Slog.v(
TAG, "ensureActivitiesVisible behind " + top
+ " configChanges=0x" + Integer.toHexString(configChanges));
@@ -1147,7 +1150,6 @@
// If the top activity is not fullscreen, then we need to
// make sure any activities under it are now visible.
boolean aboveTop = true;
- boolean showHomeBehindStack = false;
boolean behindFullscreen = !isStackVisible();
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
@@ -1235,11 +1237,9 @@
// At this point, nothing else needs to be shown
if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r);
behindFullscreen = true;
- showHomeBehindStack = false;
- } else if (isActivityOverHome(r)) {
+ } else if (!isHomeStack() && r.frontOfTask && task.mOnTopOfHome) {
if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
- showHomeBehindStack = true;
- behindFullscreen = !isHomeStack() && r.frontOfTask && task.mOnTopOfHome;
+ behindFullscreen = true;
}
} else {
if (DEBUG_VISBILITY) Slog.v(
@@ -1289,7 +1289,6 @@
}
}
}
- return showHomeBehindStack;
}
void convertToTranslucent(ActivityRecord r) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 00327ac..ce3d853 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2455,21 +2455,12 @@
void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
// First the front stacks. In case any are not fullscreen and are in front of home.
- boolean showHomeBehindStack = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
final int topStackNdx = stacks.size() - 1;
for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
- if (stackNdx == topStackNdx) {
- // Top stack.
- showHomeBehindStack =
- stack.ensureActivitiesVisibleLocked(starting, configChanges);
- } else {
- // Back stack.
- stack.ensureActivitiesVisibleLocked(starting, configChanges,
- showHomeBehindStack);
- }
+ stack.ensureActivitiesVisibleLocked(starting, configChanges);
}
}
}
diff --git a/services/core/java/com/android/server/am/UsageStatsService.java b/services/core/java/com/android/server/am/UsageStatsService.java
index 42cf900..4a5a554 100644
--- a/services/core/java/com/android/server/am/UsageStatsService.java
+++ b/services/core/java/com/android/server/am/UsageStatsService.java
@@ -17,26 +17,31 @@
package com.android.server.am;
import android.app.AppGlobals;
+import android.app.AppOpsManager;
+import android.app.UsageStats;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.res.Configuration;
import android.os.Binder;
import android.os.IBinder;
import android.os.FileUtils;
import android.os.Parcel;
+import android.os.ParcelableParcel;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.text.format.DateFormat;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.Slog;
+import android.util.TimeUtils;
import android.util.Xml;
import com.android.internal.app.IUsageStats;
import com.android.internal.content.PackageMonitor;
-import com.android.internal.os.PkgUsageStats;
import com.android.internal.util.FastXmlSerializer;
import org.xmlpull.v1.XmlPullParser;
@@ -46,7 +51,6 @@
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
@@ -55,8 +59,6 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -75,7 +77,7 @@
private static final String TAG = "UsageStats";
// Current on-disk Parcel version
- private static final int VERSION = 1008;
+ private static final int VERSION = 1010;
private static final int CHECKIN_VERSION = 4;
@@ -94,13 +96,10 @@
static IUsageStats sService;
private Context mContext;
- // structure used to maintain statistics since the last checkin.
- final private ArrayMap<String, PkgUsageStatsExtended> mStats
- = new ArrayMap<String, PkgUsageStatsExtended>();
+ private AppOpsManager mAppOps;
- // Maintains the last time any component was resumed, for all time.
- final private ArrayMap<String, ArrayMap<String, Long>> mLastResumeTimes
- = new ArrayMap<String, ArrayMap<String, Long>>();
+ // structure used to maintain statistics since the last checkin.
+ private LocalUsageStats mStats = new LocalUsageStats();
// To remove last-resume time stats when a pacakge is removed.
private PackageMonitor mPackageMonitor;
@@ -115,6 +114,7 @@
private String mLastResumedPkg;
private String mLastResumedComp;
private boolean mIsResumed;
+ private ConfigUsageStatsExtended mCurrentConfigStats;
private File mFile;
private AtomicFile mHistoryFile;
private String mFileLeaf;
@@ -127,6 +127,30 @@
private final AtomicLong mLastWriteElapsedTime = new AtomicLong(0);
private final AtomicBoolean mUnforcedDiskWriteRunning = new AtomicBoolean(false);
+ static class LocalUsageStats extends UsageStats {
+ public LocalUsageStats() {
+ }
+ public LocalUsageStats(Parcel in, boolean extended) {
+ super(in, extended);
+ }
+ @Override
+ public PackageStats onNewPackageStats(String pkgName) {
+ return new PkgUsageStatsExtended(pkgName);
+ }
+ @Override
+ public PackageStats onNewPackageStats(Parcel in) {
+ return new PkgUsageStatsExtended(in);
+ }
+ @Override
+ public ConfigurationStats onNewConfigurationStats(Configuration config) {
+ return new ConfigUsageStatsExtended(config);
+ }
+ @Override
+ public ConfigurationStats onNewConfigurationStats(Parcel source) {
+ return new ConfigUsageStatsExtended(source);
+ }
+ }
+
static class TimeStats {
int mCount;
final int[] mTimes = new int[NUM_LAUNCH_TIME_BINS];
@@ -166,27 +190,18 @@
}
}
- static class PkgUsageStatsExtended {
+ static class PkgUsageStatsExtended extends UsageStats.PackageStats {
final ArrayMap<String, TimeStats> mLaunchTimes
= new ArrayMap<String, TimeStats>();
final ArrayMap<String, TimeStats> mFullyDrawnTimes
= new ArrayMap<String, TimeStats>();
- int mLaunchCount;
- long mUsageTime;
- long mPausedTime;
- long mResumedTime;
- PkgUsageStatsExtended() {
- mLaunchCount = 0;
- mUsageTime = 0;
+ PkgUsageStatsExtended(String pkgName) {
+ super(pkgName);
}
PkgUsageStatsExtended(Parcel in) {
- mLaunchCount = in.readInt();
- mUsageTime = in.readLong();
- if (localLOGV) Slog.v(TAG, "Launch count: " + mLaunchCount
- + ", Usage time:" + mUsageTime);
-
+ super(in);
final int numLaunchTimeStats = in.readInt();
if (localLOGV) Slog.v(TAG, "Reading launch times: " + numLaunchTimeStats);
mLaunchTimes.ensureCapacity(numLaunchTimeStats);
@@ -208,18 +223,6 @@
}
}
- void updateResume(String comp, boolean launched) {
- if (launched) {
- mLaunchCount++;
- }
- mResumedTime = SystemClock.elapsedRealtime();
- }
-
- void updatePause() {
- mPausedTime = SystemClock.elapsedRealtime();
- mUsageTime += (mPausedTime - mResumedTime);
- }
-
void addLaunchCount(String comp) {
TimeStats times = mLaunchTimes.get(comp);
if (times == null) {
@@ -247,9 +250,7 @@
times.add(millis);
}
- void writeToParcel(Parcel out) {
- out.writeInt(mLaunchCount);
- out.writeLong(mUsageTime);
+ public void writeExtendedToParcel(Parcel out, int parcelableFlags) {
final int numLaunchTimeStats = mLaunchTimes.size();
out.writeInt(numLaunchTimeStats);
for (int i=0; i<numLaunchTimeStats; i++) {
@@ -264,11 +265,21 @@
}
}
- void clear() {
+ @Override
+ public boolean clearUsageTimes() {
mLaunchTimes.clear();
mFullyDrawnTimes.clear();
- mLaunchCount = 0;
- mUsageTime = 0;
+ return super.clearUsageTimes();
+ }
+ }
+
+ static class ConfigUsageStatsExtended extends UsageStats.ConfigurationStats {
+ ConfigUsageStatsExtended(Configuration config) {
+ super(config);
+ }
+
+ ConfigUsageStatsExtended(Parcel in) {
+ super(in);
}
}
@@ -364,18 +375,9 @@
+ VERSION + "; dropping");
return;
}
- int N = in.readInt();
- while (N > 0) {
- N--;
- String pkgName = in.readString();
- if (pkgName == null) {
- break;
- }
- if (localLOGV) Slog.v(TAG, "Reading package #" + N + ": " + pkgName);
- PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in);
- synchronized (mStatsLock) {
- mStats.put(pkgName, pus);
- }
+ LocalUsageStats stats = new LocalUsageStats(in, true);
+ synchronized (mStatsLock) {
+ mStats = stats;
}
}
@@ -419,12 +421,9 @@
try {
long lastResumeTime = Long.parseLong(lastResumeTimeStr);
synchronized (mStatsLock) {
- ArrayMap<String, Long> lrt = mLastResumeTimes.get(pkg);
- if (lrt == null) {
- lrt = new ArrayMap<String, Long>();
- mLastResumeTimes.put(pkg, lrt);
- }
- lrt.put(comp, lastResumeTime);
+ PkgUsageStatsExtended pus = (PkgUsageStatsExtended)
+ mStats.getOrCreatePackageStats(pkg);
+ pus.componentResumeTimes.put(comp, lastResumeTime);
}
} catch (NumberFormatException e) {
}
@@ -543,6 +542,15 @@
return;
}
+ Parcel out = Parcel.obtain();
+ synchronized (mStatsLock) {
+ out.writeInt(VERSION);
+ mStats.writeExtendedToParcel(out, 0);
+ if (dayChanged) {
+ mStats.clearUsageTimes();
+ }
+ }
+
synchronized (mFileLock) {
// Get the most recent file
mFileLeaf = getCurrentDateStr(FILE_PREFIX);
@@ -553,6 +561,7 @@
if (!backupFile.exists()) {
if (!mFile.renameTo(backupFile)) {
Slog.w(TAG, "Failed to persist new stats");
+ out.recycle();
return;
}
} else {
@@ -562,14 +571,10 @@
try {
// Write mStats to file
- writeStatsFLOCK(mFile);
+ writeStatsFLOCK(mFile, out);
mLastWriteElapsedTime.set(currElapsedTime);
if (dayChanged) {
mLastWriteDay.set(curDay);
- // clear stats
- synchronized (mStats) {
- mStats.clear();
- }
mFile = new File(mDir, mFileLeaf);
checkFileLimitFLOCK();
}
@@ -590,17 +595,15 @@
backupFile.renameTo(mFile);
}
}
+ out.recycle();
}
if (localLOGV) Slog.d(TAG, "Dumped usage stats.");
}
- private void writeStatsFLOCK(File file) throws IOException {
+ private void writeStatsFLOCK(File file, Parcel parcel) throws IOException {
FileOutputStream stream = new FileOutputStream(file);
try {
- Parcel out = Parcel.obtain();
- writeStatsToParcelFLOCK(out);
- stream.write(out.marshall());
- out.recycle();
+ stream.write(parcel.marshall());
stream.flush();
} finally {
FileUtils.sync(stream);
@@ -608,29 +611,14 @@
}
}
- private void writeStatsToParcelFLOCK(Parcel out) {
- synchronized (mStatsLock) {
- out.writeInt(VERSION);
- Set<String> keys = mStats.keySet();
- out.writeInt(keys.size());
- for (String key : keys) {
- PkgUsageStatsExtended pus = mStats.get(key);
- out.writeString(key);
- pus.writeToParcel(out);
- }
- }
- }
-
/** Filter out stats for any packages which aren't present anymore. */
private void filterHistoryStats() {
synchronized (mStatsLock) {
IPackageManager pm = AppGlobals.getPackageManager();
- for (int i=0; i<mLastResumeTimes.size(); i++) {
- String pkg = mLastResumeTimes.keyAt(i);
+ for (int i=mStats.mPackages.size()-1; i>=0; i--) {
try {
- if (pm.getPackageUid(pkg, 0) < 0) {
- mLastResumeTimes.removeAt(i);
- i--;
+ if (pm.getPackageUid(mStats.mPackages.valueAt(i).getPackageName(), 0) < 0) {
+ mStats.mPackages.removeAt(i);
}
} catch (RemoteException e) {
}
@@ -648,10 +636,12 @@
out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
out.startTag(null, "usage-history");
synchronized (mStatsLock) {
- for (int i=0; i<mLastResumeTimes.size(); i++) {
+ int NP = mStats.mPackages.size();
+ for (int i=0; i<NP; i++) {
+ UsageStats.PackageStats ps = mStats.mPackages.valueAt(i);
out.startTag(null, "pkg");
- out.attribute(null, "name", mLastResumeTimes.keyAt(i));
- ArrayMap<String, Long> comp = mLastResumeTimes.valueAt(i);
+ out.attribute(null, "name", ps.getPackageName());
+ ArrayMap<String, Long> comp = ps.componentResumeTimes;
for (int j=0; j<comp.size(); j++) {
out.startTag(null, "comp");
out.attribute(null, "name", comp.keyAt(j));
@@ -678,6 +668,10 @@
ServiceManager.addService(SERVICE_NAME, asBinder());
}
+ public void systemReady() {
+ mAppOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE);
+ }
+
/**
* Start watching packages to remove stats when a package is uninstalled.
* May only be called when the package manager is ready.
@@ -687,7 +681,7 @@
@Override
public void onPackageRemovedAllUsers(String packageName, int uid) {
synchronized (mStatsLock) {
- mLastResumeTimes.remove(packageName);
+ mStats.mPackages.remove(packageName);
}
}
};
@@ -729,9 +723,10 @@
// to recover.
if (REPORT_UNEXPECTED) Slog.i(TAG, "Unexpected resume of " + pkgName
+ " while already resumed in " + mLastResumedPkg);
- PkgUsageStatsExtended pus = mStats.get(mLastResumedPkg);
+ PkgUsageStatsExtended pus = (PkgUsageStatsExtended)mStats.getPackageStats(
+ mLastResumedPkg);
if (pus != null) {
- pus.updatePause();
+ pus.pause();
}
}
}
@@ -744,22 +739,13 @@
mLastResumedComp = componentName.getClassName();
if (localLOGV) Slog.i(TAG, "started component:" + pkgName);
- PkgUsageStatsExtended pus = mStats.get(pkgName);
- if (pus == null) {
- pus = new PkgUsageStatsExtended();
- mStats.put(pkgName, pus);
- }
- pus.updateResume(mLastResumedComp, !samePackage);
+ PkgUsageStatsExtended pus = (PkgUsageStatsExtended)
+ mStats.getOrCreatePackageStats(pkgName);
+ pus.resume(!samePackage);
if (!sameComp) {
pus.addLaunchCount(mLastResumedComp);
}
-
- ArrayMap<String, Long> componentResumeTimes = mLastResumeTimes.get(pkgName);
- if (componentResumeTimes == null) {
- componentResumeTimes = new ArrayMap<String, Long>();
- mLastResumeTimes.put(pkgName, componentResumeTimes);
- }
- componentResumeTimes.put(mLastResumedComp, System.currentTimeMillis());
+ pus.componentResumeTimes.put(mLastResumedComp, System.currentTimeMillis());
}
}
@@ -782,13 +768,13 @@
if (localLOGV) Slog.i(TAG, "paused component:"+pkgName);
- PkgUsageStatsExtended pus = mStats.get(pkgName);
+ PkgUsageStatsExtended pus = (PkgUsageStatsExtended)mStats.getPackageStats(pkgName);
if (pus == null) {
// Weird some error here
Slog.i(TAG, "No package stats for pkg:"+pkgName);
return;
}
- pus.updatePause();
+ pus.pause();
}
// Persist current data to file if needed.
@@ -808,7 +794,7 @@
writeStatsToFile(false, false);
synchronized (mStatsLock) {
- PkgUsageStatsExtended pus = mStats.get(pkgName);
+ PkgUsageStatsExtended pus = (PkgUsageStatsExtended)mStats.getPackageStats(pkgName);
if (pus != null) {
pus.addLaunchTime(componentName.getClassName(), millis);
}
@@ -827,13 +813,29 @@
writeStatsToFile(false, false);
synchronized (mStatsLock) {
- PkgUsageStatsExtended pus = mStats.get(pkgName);
+ PkgUsageStatsExtended pus = (PkgUsageStatsExtended)mStats.getPackageStats(pkgName);
if (pus != null) {
pus.addFullyDrawnTime(componentName.getClassName(), millis);
}
}
}
+ public void noteStartConfig(Configuration config) {
+ enforceCallingPermission();
+ synchronized (mStatsLock) {
+ config = new Configuration(config);
+ ConfigUsageStatsExtended cus = (ConfigUsageStatsExtended)
+ mStats.getOrCreateConfigurationStats(config);
+ if (cus != mCurrentConfigStats) {
+ if (mCurrentConfigStats != null) {
+ mCurrentConfigStats.stop();
+ }
+ cus.start();
+ mCurrentConfigStats = cus;
+ }
+ }
+ }
+
public void enforceCallingPermission() {
if (Binder.getCallingPid() == Process.myPid()) {
return;
@@ -843,53 +845,71 @@
}
@Override
- public PkgUsageStats getPkgUsageStats(ComponentName componentName) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.PACKAGE_USAGE_STATS, null);
+ public UsageStats.PackageStats getPkgUsageStats(String callingPkg,
+ ComponentName componentName) {
+ checkCallerPermission(callingPkg, "getPkgUsageStats");
String pkgName;
if ((componentName == null) ||
((pkgName = componentName.getPackageName()) == null)) {
return null;
}
synchronized (mStatsLock) {
- PkgUsageStatsExtended pus = mStats.get(pkgName);
- Map<String, Long> lastResumeTimes = mLastResumeTimes.get(pkgName);
- if (pus == null && lastResumeTimes == null) {
+ PkgUsageStatsExtended pus = (PkgUsageStatsExtended)mStats.getPackageStats(pkgName);
+ if (pus == null) {
return null;
}
- int launchCount = pus != null ? pus.mLaunchCount : 0;
- long usageTime = pus != null ? pus.mUsageTime : 0;
- return new PkgUsageStats(pkgName, launchCount, usageTime, lastResumeTimes);
+ return new UsageStats.PackageStats(pus);
}
}
@Override
- public PkgUsageStats[] getAllPkgUsageStats() {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.PACKAGE_USAGE_STATS, null);
+ public UsageStats.PackageStats[] getAllPkgUsageStats(String callingPkg) {
+ checkCallerPermission(callingPkg, "getAllPkgUsageStats");
synchronized (mStatsLock) {
- int size = mLastResumeTimes.size();
- if (size <= 0) {
+ int NP = mStats.mPackages.size();
+ if (NP <= 0) {
return null;
}
- PkgUsageStats retArr[] = new PkgUsageStats[size];
- for (int i=0; i<size; i++) {
- String pkg = mLastResumeTimes.keyAt(i);
- long usageTime = 0;
- int launchCount = 0;
-
- PkgUsageStatsExtended pus = mStats.get(pkg);
- if (pus != null) {
- usageTime = pus.mUsageTime;
- launchCount = pus.mLaunchCount;
- }
- retArr[i] = new PkgUsageStats(pkg, launchCount, usageTime,
- mLastResumeTimes.valueAt(i));
+ UsageStats.PackageStats retArr[] = new UsageStats.PackageStats[NP];
+ for (int p=0; p<NP; p++) {
+ UsageStats.PackageStats ps = mStats.mPackages.valueAt(p);
+ retArr[p] = new UsageStats.PackageStats(ps);
}
return retArr;
}
}
+ @Override
+ public ParcelableParcel getCurrentStats(String callingPkg) {
+ checkCallerPermission(callingPkg, "getCurrentStats");
+ synchronized (mStatsLock) {
+ ParcelableParcel out = new ParcelableParcel(null);
+ mStats.writeToParcel(out.getParcel(), 0);
+ return out;
+ }
+ }
+
+ private void checkCallerPermission(String callingPkg, String callingOp) {
+ // Because the permission for this is system-only, its use with
+ // app ops is a little different: the op is disabled by default,
+ // and enabling it allows apps to get access even if they don't
+ // hold the permission.
+ int mode = mAppOps.noteOpNoThrow(AppOpsManager.OP_GET_USAGE_STATS, Binder.getCallingUid(),
+ callingPkg);
+ if (mode == AppOpsManager.MODE_ALLOWED) {
+ return;
+ } else if (mode != AppOpsManager.MODE_IGNORED) {
+ if (mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.PACKAGE_USAGE_STATS)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ }
+
+ String msg = "Package " + callingPkg + " not allowed to call " + callingOp;
+ throw new SecurityException(msg);
+ }
+
static byte[] readFully(FileInputStream stream) throws IOException {
int pos = 0;
int avail = stream.available();
@@ -963,31 +983,28 @@
return;
}
- pw.println(sb.toString());
- int N = in.readInt();
+ final LocalUsageStats stats = new LocalUsageStats(in, true);
+ final long time = SystemClock.elapsedRealtime();
- while (N > 0) {
- N--;
- String pkgName = in.readString();
- if (pkgName == null) {
- break;
- }
+ pw.println(sb.toString());
+ int NP = stats.mPackages.size();
+ for (int p=0; p<NP; p++) {
+ PkgUsageStatsExtended pus = (PkgUsageStatsExtended)stats.mPackages.valueAt(p);
sb.setLength(0);
- PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in);
- if (packages != null && !packages.contains(pkgName)) {
+ if (packages != null && !packages.contains(pus.getPackageName())) {
// This package has not been requested -- don't print
// anything for it.
} else if (isCompactOutput) {
sb.append("P:");
- sb.append(pkgName);
+ sb.append(pus.getPackageName());
sb.append(',');
- sb.append(pus.mLaunchCount);
+ sb.append(pus.getLaunchCount());
sb.append(',');
- sb.append(pus.mUsageTime);
+ sb.append(pus.getUsageTime(time));
sb.append('\n');
final int NLT = pus.mLaunchTimes.size();
for (int i=0; i<NLT; i++) {
- sb.append("A:");
+ sb.append("L:");
String activity = pus.mLaunchTimes.keyAt(i);
sb.append(activity);
TimeStats times = pus.mLaunchTimes.valueAt(i);
@@ -1001,7 +1018,7 @@
}
final int NFDT = pus.mFullyDrawnTimes.size();
for (int i=0; i<NFDT; i++) {
- sb.append("A:");
+ sb.append("D:");
String activity = pus.mFullyDrawnTimes.keyAt(i);
sb.append(activity);
TimeStats times = pus.mFullyDrawnTimes.valueAt(i);
@@ -1011,15 +1028,23 @@
}
sb.append('\n');
}
+ final int NC = pus.componentResumeTimes.size();
+ for (int c=0; c<NC; c++) {
+ pw.print("R:"); pw.print(pus.componentResumeTimes.keyAt(c)); pw.print(",");
+ pw.println(pus.componentResumeTimes.valueAt(c));
+ }
} else {
sb.append(" ");
- sb.append(pkgName);
- sb.append(": ");
- sb.append(pus.mLaunchCount);
- sb.append(" times, ");
- sb.append(pus.mUsageTime);
- sb.append(" ms");
+ sb.append(pus.getPackageName());
+ if (pus.getLaunchCount() != 0 || pus.getUsageTime(time) != 0) {
+ sb.append(": ");
+ sb.append(pus.getLaunchCount());
+ sb.append(" times, ");
+ TimeUtils.formatDuration(pus.getUsageTime(time), sb);
+ } else {
+ sb.append(":");
+ }
sb.append('\n');
final int NLT = pus.mLaunchTimes.size();
for (int i=0; i<NLT; i++) {
@@ -1084,10 +1109,50 @@
}
sb.append('\n');
}
+ final int NC = pus.componentResumeTimes.size();
+ for (int c=0; c<NC; c++) {
+ sb.append(" ");
+ sb.append(pus.componentResumeTimes.keyAt(c));
+ sb.append(" last resumed ");
+ sb.append(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
+ pus.componentResumeTimes.valueAt(c)).toString());
+ sb.append('\n');
+ }
}
pw.write(sb.toString());
}
+ if (packages == null) {
+ int NC = stats.mConfigurations.size();
+ for (int c=0; c<NC; c++) {
+ ConfigUsageStatsExtended cus
+ = (ConfigUsageStatsExtended)stats.mConfigurations.valueAt(c);
+ sb.setLength(0);
+ if (isCompactOutput) {
+ sb.append("C:"); sb.append(cus.getConfiguration().toString());
+ sb.append(","); sb.append(cus.getUsageCount()); sb.append(",");
+ sb.append(cus.getUsageTime(time));
+ } else {
+ sb.append(" ");
+ sb.append(cus.getConfiguration().toString());
+ sb.append(":\n");
+ if (cus.getUsageCount() != 0 || cus.getUsageTime(time) != 0) {
+ sb.append(" Used ");
+ sb.append(cus.getUsageCount());
+ sb.append(" times, ");
+ TimeUtils.formatDuration(cus.getUsageTime(time), sb);
+ sb.append("\n");
+ }
+ if (cus.getLastUsedTime() > 0) {
+ sb.append(" Last used: ");
+ sb.append(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
+ cus.getLastUsedTime()).toString());
+ sb.append("\n");
+ }
+ }
+ pw.write(sb.toString());
+ }
+ }
}
/**
@@ -1174,5 +1239,4 @@
collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint, packages);
}
}
-
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 54cb035..0f5805c 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -323,6 +323,10 @@
mHandler.sendEmptyMessage(MSG_RELOAD_DEVICE_ALIASES);
mHandler.sendEmptyMessage(MSG_UPDATE_KEYBOARD_LAYOUTS);
+
+ if (mWiredAccessoryCallbacks != null) {
+ mWiredAccessoryCallbacks.systemReady();
+ }
}
private void reloadKeyboardLayouts() {
@@ -1588,6 +1592,7 @@
*/
public interface WiredAccessoryCallbacks {
public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask);
+ public void systemReady();
}
/**
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index fce86e8..4698587 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -444,7 +444,7 @@
public static final class NotificationRecord
{
final StatusBarNotification sbn;
- final SingleNotificationStats stats = new SingleNotificationStats();
+ SingleNotificationStats stats;
IBinder statusBarKey;
NotificationRecord(StatusBarNotification sbn)
@@ -1639,7 +1639,7 @@
} else {
old = mNotificationList.get(index);
mNotificationList.set(index, r);
- mUsageStats.registerUpdatedByApp(r);
+ mUsageStats.registerUpdatedByApp(r, old);
// Make sure we don't lose the foreground service state.
if (old != null) {
notification.flags |=
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index 45ab3d3..a60e95b 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -58,6 +58,7 @@
* Called when a notification has been posted.
*/
public synchronized void registerPostedByApp(NotificationRecord notification) {
+ notification.stats = new SingleNotificationStats();
notification.stats.posttimeElapsedMs = SystemClock.elapsedRealtime();
for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
stats.numPostedByApp++;
@@ -68,7 +69,8 @@
/**
* Called when a notification has been updated.
*/
- public void registerUpdatedByApp(NotificationRecord notification) {
+ public void registerUpdatedByApp(NotificationRecord notification, NotificationRecord old) {
+ notification.stats = old.stats;
for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
stats.numUpdatedByApp++;
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 4f5326f..60212bf 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -288,6 +288,20 @@
return users;
}
+ @Override
+ public UserInfo getProfileParent(int userHandle) {
+ checkManageUsersPermission("get the profile parent");
+ synchronized (mPackagesLock) {
+ UserInfo profile = getUserInfoLocked(userHandle);
+ int parentUserId = profile.profileGroupId;
+ if (parentUserId == UserInfo.NO_PROFILE_GROUP_ID) {
+ return null;
+ } else {
+ return getUserInfoLocked(parentUserId);
+ }
+ }
+ }
+
private boolean isProfileOf(UserInfo user, UserInfo profile) {
return user.id == profile.id ||
(user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
@@ -743,6 +757,9 @@
writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_CELL_BROADCASTS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_APPS);
+ writeBoolean(serializer, restrictions, UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
+ writeBoolean(serializer, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE);
+ writeBoolean(serializer, restrictions, UserManager.DISALLOW_ADJUST_VOLUME);
serializer.endTag(null, TAG_RESTRICTIONS);
}
serializer.endTag(null, TAG_USER);
@@ -891,6 +908,10 @@
readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_CELL_BROADCASTS);
readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_APPS);
+ readBoolean(parser, restrictions,
+ UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
+ readBoolean(parser, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE);
+ readBoolean(parser, restrictions, UserManager.DISALLOW_ADJUST_VOLUME);
}
}
}
@@ -1015,17 +1036,6 @@
}
}
- private int getNextProfileGroupIdLocked() {
- int maxGroupId = UserInfo.NO_PROFILE_GROUP_ID;
- for (int i = 0; i < mUsers.size(); i++) {
- UserInfo ui = mUsers.valueAt(i);
- if (maxGroupId < ui.profileGroupId) {
- maxGroupId = ui.profileGroupId;
- }
- }
- return maxGroupId + 1;
- }
-
@Override
public UserInfo createProfileForUser(String name, int flags, int userId) {
checkManageUsersPermission("Only the system can create users");
@@ -1042,16 +1052,16 @@
return createUserInternal(name, flags, UserHandle.USER_NULL);
}
- private UserInfo createUserInternal(String name, int flags, int profileId) {
+ private UserInfo createUserInternal(String name, int flags, int parentId) {
final long ident = Binder.clearCallingIdentity();
UserInfo userInfo = null;
try {
synchronized (mInstallLock) {
synchronized (mPackagesLock) {
- UserInfo profile = null;
- if (profileId != UserHandle.USER_NULL) {
- profile = getUserInfoLocked(profileId);
- if (profile == null) return null;
+ UserInfo parent = null;
+ if (parentId != UserHandle.USER_NULL) {
+ parent = getUserInfoLocked(parentId);
+ if (parent == null) return null;
}
if (isUserLimitReachedLocked()) return null;
int userId = getNextAvailableIdLocked();
@@ -1064,12 +1074,12 @@
Environment.getUserSystemDirectory(userInfo.id).mkdirs();
mUsers.put(userId, userInfo);
writeUserListLocked();
- if (profile != null) {
- if (profile.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
- profile.profileGroupId = getNextProfileGroupIdLocked();
- writeUserLocked(profile);
+ if (parent != null) {
+ if (parent.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
+ parent.profileGroupId = parent.id;
+ writeUserLocked(parent);
}
- userInfo.profileGroupId = profile.profileGroupId;
+ userInfo.profileGroupId = parent.profileGroupId;
}
writeUserLocked(userInfo);
mPm.createNewUserLILPw(userId, userPath);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 9039236..99ec242 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -116,7 +116,8 @@
/** Fraction of animation at which the recents thumbnail becomes completely transparent */
private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.25f;
- private static final long DEFAULT_APP_TRANSITION_DURATION = 250;
+ private static final int DEFAULT_APP_TRANSITION_DURATION = 250;
+ private static final int THUMBNAIL_APP_TRANSITION_DURATION = 225;
private final Context mContext;
private final Handler mH;
@@ -160,6 +161,7 @@
private final int mConfigShortAnimTime;
private final Interpolator mDecelerateInterpolator;
private final Interpolator mThumbnailFadeoutInterpolator;
+ private final Interpolator mThumbnailCubicInterpolator;
private int mCurrentUserId = 0;
@@ -170,6 +172,8 @@
com.android.internal.R.integer.config_shortAnimTime);
mDecelerateInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.decelerate_cubic);
+ mThumbnailCubicInterpolator = AnimationUtils.loadInterpolator(context,
+ com.android.internal.R.interpolator.fast_out_slow_in);
mThumbnailFadeoutInterpolator = new Interpolator() {
@Override
public float getInterpolation(float input) {
@@ -401,11 +405,23 @@
/**
* Prepares the specified animation with a standard duration, interpolator, etc.
*/
+ Animation prepareThumbnailAnimationWithDuration(Animation a, int appWidth, int appHeight,
+ int duration, Interpolator interpolator) {
+ a.setDuration(duration);
+ a.setFillAfter(true);
+ a.setInterpolator(interpolator);
+ a.initialize(appWidth, appHeight, appWidth, appHeight);
+ return a;
+ }
+
+ /**
+ * Prepares the specified animation with a standard duration, interpolator, etc.
+ */
Animation prepareThumbnailAnimation(Animation a, int appWidth, int appHeight, int transit) {
// Pick the desired duration. If this is an inter-activity transition,
// it is the standard duration for that. Otherwise we use the longer
// task transition duration.
- final long duration;
+ final int duration;
switch (transit) {
case TRANSIT_ACTIVITY_OPEN:
case TRANSIT_ACTIVITY_CLOSE:
@@ -415,11 +431,8 @@
duration = DEFAULT_APP_TRANSITION_DURATION;
break;
}
- a.setDuration(duration);
- a.setFillAfter(true);
- a.setInterpolator(mDecelerateInterpolator);
- a.initialize(appWidth, appHeight, appWidth, appHeight);
- return a;
+ return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration,
+ mDecelerateInterpolator);
}
/**
@@ -594,7 +607,8 @@
throw new RuntimeException("Invalid thumbnail transition state");
}
- return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
+ return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight,
+ THUMBNAIL_APP_TRANSITION_DURATION, mThumbnailCubicInterpolator);
}
/**
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9a9f1c8..1980d1e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -97,6 +97,7 @@
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
@@ -113,6 +114,8 @@
private static final String DEVICE_POLICIES_XML = "device_policies.xml";
+ private static final String LOCK_TASK_COMPONENTS_XML = "lock-task-component";
+
private static final int REQUEST_EXPIRE_PASSWORD = 5571;
private static final long MS_PER_DAY = 86400 * 1000;
@@ -127,6 +130,7 @@
private static final boolean DBG = false;
final Context mContext;
+ final UserManager mUserManager;
final PowerManager.WakeLock mWakeLock;
IPowerManager mIPowerManager;
@@ -182,6 +186,9 @@
final ArrayList<ActiveAdmin> mAdminList
= new ArrayList<ActiveAdmin>();
+ // This is the list of component allowed to start lock task mode.
+ final List<ComponentName> mLockTaskComponents = new ArrayList<ComponentName>();
+
public DevicePolicyData(int userHandle) {
mUserHandle = userHandle;
}
@@ -203,7 +210,7 @@
+ action + " for user " + userHandle);
mHandler.post(new Runnable() {
public void run() {
- handlePasswordExpirationNotification(getUserData(userHandle));
+ handlePasswordExpirationNotification(userHandle);
}
});
}
@@ -605,6 +612,7 @@
*/
public DevicePolicyManagerService(Context context) {
mContext = context;
+ mUserManager = UserManager.get(mContext);
mHasFeature = context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_DEVICE_ADMIN);
mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE))
@@ -812,6 +820,9 @@
sendAdminCommandLocked(admin, action, null);
}
+ /**
+ * Send an update to one specific admin, get notified when that admin returns a result.
+ */
void sendAdminCommandLocked(ActiveAdmin admin, String action, BroadcastReceiver result) {
Intent intent = new Intent(action);
intent.setComponent(admin.info.getComponent());
@@ -826,12 +837,15 @@
}
}
+ /**
+ * Send an update to all admins of a user that enforce a specified policy.
+ */
void sendAdminCommandLocked(String action, int reqPolicy, int userHandle) {
final DevicePolicyData policy = getUserData(userHandle);
final int count = policy.mAdminList.size();
if (count > 0) {
for (int i = 0; i < count; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
+ final ActiveAdmin admin = policy.mAdminList.get(i);
if (admin.info.usesPolicy(reqPolicy)) {
sendAdminCommandLocked(admin, action);
}
@@ -839,6 +853,19 @@
}
}
+ /**
+ * Send an update intent to all admins of a user and its profiles. Only send to admins that
+ * enforce a specified policy.
+ */
+ private void sendAdminCommandToSelfAndProfilesLocked(String action, int reqPolicy,
+ int userHandle) {
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo ui : profiles) {
+ int id = ui.getUserHandle().getIdentifier();
+ sendAdminCommandLocked(action, reqPolicy, id);
+ }
+ }
+
void removeActiveAdminLocked(final ComponentName adminReceiver, int userHandle) {
final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (admin != null) {
@@ -955,6 +982,13 @@
out.endTag(null, "active-password");
}
+ for (int i=0; i<policy.mLockTaskComponents.size(); i++) {
+ ComponentName component = policy.mLockTaskComponents.get(i);
+ out.startTag(null, LOCK_TASK_COMPONENTS_XML);
+ out.attribute(null, "name", component.flattenToString());
+ out.endTag(null, LOCK_TASK_COMPONENTS_XML);
+ }
+
out.endTag(null, "policies");
out.endDocument();
@@ -1004,6 +1038,7 @@
}
type = parser.next();
int outerDepth = parser.getDepth();
+ policy.mLockTaskComponents.clear();
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
@@ -1056,6 +1091,11 @@
policy.mActivePasswordNonLetter = Integer.parseInt(
parser.getAttributeValue(null, "nonletter"));
XmlUtils.skipCurrentTag(parser);
+ } else if (LOCK_TASK_COMPONENTS_XML.equals(tag)) {
+ policy.mLockTaskComponents.add
+ (ComponentName.unflattenFromString
+ (parser.getAttributeValue(null, "name")));
+ XmlUtils.skipCurrentTag(parser);
} else {
Slog.w(LOG_TAG, "Unknown tag: " + tag);
XmlUtils.skipCurrentTag(parser);
@@ -1171,23 +1211,29 @@
}
}
- private void handlePasswordExpirationNotification(DevicePolicyData policy) {
+ private void handlePasswordExpirationNotification(int userHandle) {
synchronized (this) {
final long now = System.currentTimeMillis();
- final int N = policy.mAdminList.size();
- if (N <= 0) {
- return;
- }
- for (int i=0; i < N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)
- && admin.passwordExpirationTimeout > 0L
- && admin.passwordExpirationDate > 0L
- && now >= admin.passwordExpirationDate - EXPIRATION_GRACE_PERIOD_MS) {
- sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING);
+
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo ui : profiles) {
+ int profileUserHandle = ui.getUserHandle().getIdentifier();
+ final DevicePolicyData policy = getUserData(profileUserHandle);
+ final int count = policy.mAdminList.size();
+ if (count > 0) {
+ for (int i = 0; i < count; i++) {
+ final ActiveAdmin admin = policy.mAdminList.get(i);
+ if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)
+ && admin.passwordExpirationTimeout > 0L
+ && now >= admin.passwordExpirationDate - EXPIRATION_GRACE_PERIOD_MS
+ && admin.passwordExpirationDate > 0L) {
+ sendAdminCommandLocked(admin,
+ DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING);
+ }
+ }
}
}
- setExpirationAlarmCheckLocked(mContext, policy);
+ setExpirationAlarmCheckLocked(mContext, getUserData(userHandle));
}
}
@@ -1197,8 +1243,7 @@
final boolean hasCert = DevicePolicyManager.hasAnyCaCertsInstalled();
if (! hasCert) {
if (intent.getAction().equals(KeyChain.ACTION_STORAGE_CHANGED)) {
- UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- for (UserInfo user : um.getUsers()) {
+ for (UserInfo user : mUserManager.getUsers()) {
notificationManager.cancelAsUser(
null, MONITORING_CERT_NOTIFICATION_ID, user.getUserHandle());
}
@@ -1237,8 +1282,7 @@
// If this is a boot intent, this will fire for each user. But if this is a storage changed
// intent, it will fire once, so we need to notify all users.
if (intent.getAction().equals(KeyChain.ACTION_STORAGE_CHANGED)) {
- UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- for (UserInfo user : um.getUsers()) {
+ for (UserInfo user : mUserManager.getUsers()) {
notificationManager.notifyAsUser(
null, MONITORING_CERT_NOTIFICATION_ID, noti, user.getUserHandle());
}
@@ -1415,18 +1459,22 @@
enforceCrossUserPermission(userHandle);
synchronized (this) {
int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
- DevicePolicyData policy = getUserData(userHandle);
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return admin != null ? admin.passwordQuality : mode;
}
- final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (mode < admin.passwordQuality) {
- mode = admin.passwordQuality;
+ // Return strictest policy for this user and profiles that are visible from this user.
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo userInfo : profiles) {
+ DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ final int N = policy.mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (mode < admin.passwordQuality) {
+ mode = admin.passwordQuality;
+ }
}
}
return mode;
@@ -1457,7 +1505,6 @@
}
enforceCrossUserPermission(userHandle);
synchronized (this) {
- DevicePolicyData policy = getUserData(userHandle);
int length = 0;
if (who != null) {
@@ -1465,11 +1512,16 @@
return admin != null ? admin.minimumPasswordLength : length;
}
- final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (length < admin.minimumPasswordLength) {
- length = admin.minimumPasswordLength;
+ // Return strictest policy for this user and profiles that are visible from this user.
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo userInfo : profiles) {
+ DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ final int N = policy.mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (length < admin.minimumPasswordLength) {
+ length = admin.minimumPasswordLength;
+ }
}
}
return length;
@@ -1500,7 +1552,6 @@
}
enforceCrossUserPermission(userHandle);
synchronized (this) {
- DevicePolicyData policy = getUserData(userHandle);
int length = 0;
if (who != null) {
@@ -1508,11 +1559,16 @@
return admin != null ? admin.passwordHistoryLength : length;
}
- final int N = policy.mAdminList.size();
- for (int i = 0; i < N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (length < admin.passwordHistoryLength) {
- length = admin.passwordHistoryLength;
+ // Return strictest policy for this user and profiles that are visible from this user.
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo userInfo : profiles) {
+ DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ final int N = policy.mAdminList.size();
+ for (int i = 0; i < N; i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (length < admin.passwordHistoryLength) {
+ length = admin.passwordHistoryLength;
+ }
}
}
return length;
@@ -1558,19 +1614,23 @@
}
enforceCrossUserPermission(userHandle);
synchronized (this) {
+ long timeout = 0L;
+
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
- return admin != null ? admin.passwordExpirationTimeout : 0L;
+ return admin != null ? admin.passwordExpirationTimeout : timeout;
}
- long timeout = 0L;
- DevicePolicyData policy = getUserData(userHandle);
- final int N = policy.mAdminList.size();
- for (int i = 0; i < N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (timeout == 0L || (admin.passwordExpirationTimeout != 0L
- && timeout > admin.passwordExpirationTimeout)) {
- timeout = admin.passwordExpirationTimeout;
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo userInfo : profiles) {
+ DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ final int N = policy.mAdminList.size();
+ for (int i = 0; i < N; i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (timeout == 0L || (admin.passwordExpirationTimeout != 0L
+ && timeout > admin.passwordExpirationTimeout)) {
+ timeout = admin.passwordExpirationTimeout;
+ }
}
}
return timeout;
@@ -1582,19 +1642,23 @@
* Returns 0 if not configured.
*/
private long getPasswordExpirationLocked(ComponentName who, int userHandle) {
+ long timeout = 0L;
+
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
- return admin != null ? admin.passwordExpirationDate : 0L;
+ return admin != null ? admin.passwordExpirationDate : timeout;
}
- long timeout = 0L;
- DevicePolicyData policy = getUserData(userHandle);
- final int N = policy.mAdminList.size();
- for (int i = 0; i < N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (timeout == 0L || (admin.passwordExpirationDate != 0
- && timeout > admin.passwordExpirationDate)) {
- timeout = admin.passwordExpirationDate;
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo userInfo : profiles) {
+ DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ final int N = policy.mAdminList.size();
+ for (int i = 0; i < N; i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (timeout == 0L || (admin.passwordExpirationDate != 0
+ && timeout > admin.passwordExpirationDate)) {
+ timeout = admin.passwordExpirationDate;
+ }
}
}
return timeout;
@@ -1641,12 +1705,16 @@
return admin != null ? admin.minimumPasswordUpperCase : length;
}
- DevicePolicyData policy = getUserData(userHandle);
- final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (length < admin.minimumPasswordUpperCase) {
- length = admin.minimumPasswordUpperCase;
+ // Return strictest policy for this user and profiles that are visible from this user.
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo userInfo : profiles) {
+ DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ final int N = policy.mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (length < admin.minimumPasswordUpperCase) {
+ length = admin.minimumPasswordUpperCase;
+ }
}
}
return length;
@@ -1681,12 +1749,16 @@
return admin != null ? admin.minimumPasswordLowerCase : length;
}
- DevicePolicyData policy = getUserData(userHandle);
- final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (length < admin.minimumPasswordLowerCase) {
- length = admin.minimumPasswordLowerCase;
+ // Return strictest policy for this user and profiles that are visible from this user.
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo userInfo : profiles) {
+ DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ final int N = policy.mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (length < admin.minimumPasswordLowerCase) {
+ length = admin.minimumPasswordLowerCase;
+ }
}
}
return length;
@@ -1724,12 +1796,16 @@
return admin != null ? admin.minimumPasswordLetters : length;
}
- DevicePolicyData policy = getUserData(userHandle);
- final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (length < admin.minimumPasswordLetters) {
- length = admin.minimumPasswordLetters;
+ // Return strictest policy for this user and profiles that are visible from this user.
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo userInfo : profiles) {
+ DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ final int N = policy.mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (length < admin.minimumPasswordLetters) {
+ length = admin.minimumPasswordLetters;
+ }
}
}
return length;
@@ -1767,12 +1843,16 @@
return admin != null ? admin.minimumPasswordNumeric : length;
}
- DevicePolicyData policy = getUserData(userHandle);
- final int N = policy.mAdminList.size();
- for (int i = 0; i < N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (length < admin.minimumPasswordNumeric) {
- length = admin.minimumPasswordNumeric;
+ // Return strictest policy for this user and profiles that are visible from this user.
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo userInfo : profiles) {
+ DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ final int N = policy.mAdminList.size();
+ for (int i = 0; i < N; i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (length < admin.minimumPasswordNumeric) {
+ length = admin.minimumPasswordNumeric;
+ }
}
}
return length;
@@ -1810,12 +1890,16 @@
return admin != null ? admin.minimumPasswordSymbols : length;
}
- DevicePolicyData policy = getUserData(userHandle);
- final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (length < admin.minimumPasswordSymbols) {
- length = admin.minimumPasswordSymbols;
+ // Return strictest policy for this user and profiles that are visible from this user.
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo userInfo : profiles) {
+ DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ final int N = policy.mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (length < admin.minimumPasswordSymbols) {
+ length = admin.minimumPasswordSymbols;
+ }
}
}
return length;
@@ -1853,12 +1937,16 @@
return admin != null ? admin.minimumPasswordNonLetter : length;
}
- DevicePolicyData policy = getUserData(userHandle);
- final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (length < admin.minimumPasswordNonLetter) {
- length = admin.minimumPasswordNonLetter;
+ // Return strictest policy for this user and profiles that are visible from this user.
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo userInfo : profiles) {
+ DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ final int N = policy.mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (length < admin.minimumPasswordNonLetter) {
+ length = admin.minimumPasswordNonLetter;
+ }
}
}
return length;
@@ -1870,8 +1958,16 @@
return true;
}
enforceCrossUserPermission(userHandle);
+
synchronized (this) {
- DevicePolicyData policy = getUserData(userHandle);
+
+ // The active password is stored in the user that runs the launcher
+ // If the user this is called from is part of a profile group, that is the parent
+ // of the group.
+ UserInfo parent = getProfileParent(userHandle);
+ int id = parent == null ? userHandle : parent.id;
+ DevicePolicyData policy = getUserData(id);
+
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(null,
@@ -1893,13 +1989,16 @@
}
public int getCurrentFailedPasswordAttempts(int userHandle) {
- enforceCrossUserPermission(userHandle);
synchronized (this) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
- return getUserData(userHandle).mFailedPasswordAttempts;
+
+ // The active password is stored in the parent.
+ DevicePolicyData policy = getUserData(getProfileParent(userHandle).id);
+
+ return policy.mFailedPasswordAttempts;
}
}
@@ -1909,6 +2008,9 @@
}
enforceCrossUserPermission(userHandle);
synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(who,
@@ -1928,7 +2030,6 @@
}
enforceCrossUserPermission(userHandle);
synchronized (this) {
- DevicePolicyData policy = getUserData(userHandle);
int count = 0;
if (who != null) {
@@ -1936,14 +2037,19 @@
return admin != null ? admin.maximumFailedPasswordsForWipe : count;
}
- final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (count == 0) {
- count = admin.maximumFailedPasswordsForWipe;
- } else if (admin.maximumFailedPasswordsForWipe != 0
- && count > admin.maximumFailedPasswordsForWipe) {
- count = admin.maximumFailedPasswordsForWipe;
+ // Return strictest policy for this user and profiles that are visible from this user.
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo userInfo : profiles) {
+ DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ final int N = policy.mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (count == 0) {
+ count = admin.maximumFailedPasswordsForWipe;
+ } else if (admin.maximumFailedPasswordsForWipe != 0
+ && count > admin.maximumFailedPasswordsForWipe) {
+ count = admin.maximumFailedPasswordsForWipe;
+ }
}
}
return count;
@@ -1955,9 +2061,11 @@
return false;
}
enforceCrossUserPermission(userHandle);
+ enforceNotManagedProfile(userHandle, "reset the password");
+
int quality;
synchronized (this) {
- // This API can only be called by an active device admin,
+ // This api can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
@@ -2135,15 +2243,19 @@
return admin != null ? admin.maximumTimeToUnlock : time;
}
- DevicePolicyData policy = getUserData(userHandle);
- final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (time == 0) {
- time = admin.maximumTimeToUnlock;
- } else if (admin.maximumTimeToUnlock != 0
- && time > admin.maximumTimeToUnlock) {
- time = admin.maximumTimeToUnlock;
+ // Return strictest policy for this user and profiles that are visible from this user.
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo userInfo : profiles) {
+ DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ final int N = policy.mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (time == 0) {
+ time = admin.maximumTimeToUnlock;
+ } else if (admin.maximumTimeToUnlock != 0
+ && time > admin.maximumTimeToUnlock) {
+ time = admin.maximumTimeToUnlock;
+ }
}
}
return time;
@@ -2301,7 +2413,7 @@
public void run() {
try {
ActivityManagerNative.getDefault().switchUser(UserHandle.USER_OWNER);
- ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
+ (mUserManager)
.removeUser(userHandle);
} catch (RemoteException re) {
// Shouldn't happen
@@ -2349,6 +2461,8 @@
return;
}
enforceCrossUserPermission(userHandle);
+ enforceNotManagedProfile(userHandle, "set the active password");
+
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
DevicePolicyData p = getUserData(userHandle);
@@ -2377,7 +2491,8 @@
saveSettingsLocked(userHandle);
updatePasswordExpirationsLocked(userHandle);
setExpirationAlarmCheckLocked(mContext, p);
- sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
+ sendAdminCommandToSelfAndProfilesLocked(
+ DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, userHandle);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -2387,26 +2502,31 @@
}
/**
- * Called any time the device password is updated. Resets all password expiration clocks.
+ * Called any time the device password is updated. Resets all password expiration clocks.
*/
private void updatePasswordExpirationsLocked(int userHandle) {
- DevicePolicyData policy = getUserData(userHandle);
- final int N = policy.mAdminList.size();
- if (N > 0) {
- for (int i=0; i<N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) {
- long timeout = admin.passwordExpirationTimeout;
- long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L;
- admin.passwordExpirationDate = expiration;
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ for (UserInfo userInfo : profiles) {
+ int profileId = userInfo.getUserHandle().getIdentifier();
+ DevicePolicyData policy = getUserData(profileId);
+ final int N = policy.mAdminList.size();
+ if (N > 0) {
+ for (int i=0; i<N; i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) {
+ long timeout = admin.passwordExpirationTimeout;
+ long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L;
+ admin.passwordExpirationDate = expiration;
+ }
+ }
}
+ saveSettingsLocked(profileId);
}
- saveSettingsLocked(userHandle);
- }
}
public void reportFailedPasswordAttempt(int userHandle) {
enforceCrossUserPermission(userHandle);
+ enforceNotManagedProfile(userHandle, "report failed password attempt");
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
@@ -2421,7 +2541,8 @@
if (max > 0 && policy.mFailedPasswordAttempts >= max) {
wipeDeviceOrUserLocked(0, userHandle);
}
- sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
+ sendAdminCommandToSelfAndProfilesLocked(
+ DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
}
} finally {
@@ -2444,7 +2565,8 @@
policy.mPasswordOwner = -1;
saveSettingsLocked(userHandle);
if (mHasFeature) {
- sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
+ sendAdminCommandToSelfAndProfilesLocked(
+ DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
}
} finally {
@@ -2473,7 +2595,7 @@
// Scan through active admins and find if anyone has already
// set the global proxy.
Set<ComponentName> compSet = policy.mAdminMap.keySet();
- for (ComponentName component : compSet) {
+ for (ComponentName component : compSet) {
ActiveAdmin ap = policy.mAdminMap.get(component);
if ((ap.specifiesGlobalProxy) && (!component.equals(who))) {
// Another admin already sets the global proxy
@@ -2502,8 +2624,11 @@
// Reset the global proxy accordingly
// Do this using system permissions, as apps cannot write to secure settings
long origId = Binder.clearCallingIdentity();
- resetGlobalProxyLocked(policy);
- Binder.restoreCallingIdentity(origId);
+ try {
+ resetGlobalProxyLocked(policy);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
return null;
}
}
@@ -2888,8 +3013,7 @@
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
- UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- if (um.getUserInfo(userHandle) == null) {
+ if (mUserManager.getUserInfo(userHandle) == null) {
// User doesn't exist.
throw new IllegalArgumentException(
"Attempted to set profile owner for invalid userId: " + userHandle);
@@ -2935,10 +3059,9 @@
int userId = UserHandle.getCallingUserId();
Slog.d(LOG_TAG, "Enabling the profile for: " + userId);
- UserManager um = UserManager.get(mContext);
long id = Binder.clearCallingIdentity();
try {
- um.setUserEnabled(userId);
+ mUserManager.setUserEnabled(userId);
Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED);
intent.putExtra(Intent.EXTRA_USER, new UserHandle(UserHandle.getCallingUserId()));
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
@@ -3002,6 +3125,30 @@
}
}
+ private void enforceNotManagedProfile(int userHandle, String message) {
+ if(isManagedProfile(userHandle)) {
+ throw new SecurityException("You can not " + message + " from a managed profile. ");
+ }
+ }
+
+ private UserInfo getProfileParent(int userHandle) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ return mUserManager.getProfileParent(userHandle);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ private boolean isManagedProfile(int userHandle) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ return mUserManager.getUserInfo(userHandle).isManagedProfile();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
private void enableIfNecessary(String packageName, int userId) {
try {
IPackageManager ipm = AppGlobals.getPackageManager();
@@ -3105,10 +3252,9 @@
}
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- UserManager um = UserManager.get(mContext);
long id = Binder.clearCallingIdentity();
try {
- um.setApplicationRestrictions(packageName, settings, userHandle);
+ mUserManager.setApplicationRestrictions(packageName, settings, userHandle);
} finally {
restoreCallingIdentity(id);
}
@@ -3172,10 +3318,9 @@
}
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- UserManager um = UserManager.get(mContext);
long id = Binder.clearCallingIdentity();
try {
- return um.getApplicationRestrictions(packageName, userHandle);
+ return mUserManager.getApplicationRestrictions(packageName, userHandle);
} finally {
restoreCallingIdentity(id);
}
@@ -3192,10 +3337,9 @@
}
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- UserManager um = UserManager.get(mContext);
long id = Binder.clearCallingIdentity();
try {
- um.setUserRestriction(key, enabled, userHandle);
+ mUserManager.setUserRestriction(key, enabled, userHandle);
} finally {
restoreCallingIdentity(id);
}
@@ -3344,4 +3488,74 @@
return resultSet.toArray(new String[resultSet.size()]);
}
}
+
+ /**
+ * Sets which componets may enter lock task mode.
+ *
+ * This function can only be called by the device owner or the profile owner.
+ * @param components The list of components allowed to enter lock task mode.
+ */
+ public void setLockTaskComponents(ComponentName[] components) throws SecurityException {
+ // Get the package names of the caller.
+ int uid = Binder.getCallingUid();
+ String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
+
+ // Check whether any of the package name is the device owner or the profile owner.
+ for (int i=0; i<packageNames.length; i++) {
+ String packageName = packageNames[i];
+ int userHandle = UserHandle.getUserId(uid);
+ String profileOwnerPackage = getProfileOwner(userHandle);
+ if (isDeviceOwner(packageName) ||
+ (profileOwnerPackage != null && profileOwnerPackage.equals(packageName))) {
+
+ // If a package name is the device owner or the profile owner,
+ // we update the component list.
+ DevicePolicyData policy = getUserData(userHandle);
+ policy.mLockTaskComponents.clear();
+ if (components != null) {
+ for (int j=0; j<components.length; j++) {
+ ComponentName component = components[j];
+ policy.mLockTaskComponents.add(component);
+ }
+ }
+
+ // Store the settings persistently.
+ saveSettingsLocked(userHandle);
+ return;
+ }
+ }
+ throw new SecurityException();
+ }
+
+ /**
+ * This function returns the list of components allowed to start the task lock mode.
+ */
+ public ComponentName[] getLockTaskComponents() {
+ int userHandle = UserHandle.USER_OWNER;
+ DevicePolicyData policy = getUserData(userHandle);
+ ComponentName[] tempArray = policy.mLockTaskComponents.toArray(new ComponentName[0]);
+ return tempArray;
+ }
+
+ /**
+ * This function lets the caller know whether the given component is allowed to start the
+ * lock task mode.
+ * @param component The component to check
+ */
+ public boolean isLockTaskPermitted(ComponentName component) {
+ // Get current user's devicepolicy
+ int uid = Binder.getCallingUid();
+ int userHandle = UserHandle.getUserId(uid);
+ DevicePolicyData policy = getUserData(userHandle);
+ for (int i=0; i<policy.mLockTaskComponents.size(); i++) {
+ ComponentName lockTaskComponent = policy.mLockTaskComponents.get(i);
+
+ // If the given component equals one of the component stored our device-owner-set
+ // list, we allow this component to start the lock task mode.
+ if (lockTaskComponent.getPackageName().equals(component.getPackageName())) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 716823c..22e2a6e 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -334,6 +334,7 @@
InputManagerService inputManager = null;
TelephonyRegistry telephonyRegistry = null;
ConsumerIrService consumerIr = null;
+ AudioService audioService = null;
boolean onlyCore = false;
boolean firstBoot = false;
@@ -769,7 +770,8 @@
if (!disableMedia && !"0".equals(SystemProperties.get("system_init.startaudioservice"))) {
try {
Slog.i(TAG, "Audio Service");
- ServiceManager.addService(Context.AUDIO_SERVICE, new AudioService(context));
+ audioService = new AudioService(context);
+ ServiceManager.addService(Context.AUDIO_SERVICE, audioService);
} catch (Throwable e) {
reportWtf("starting Audio Service", e);
}
@@ -1084,6 +1086,7 @@
final InputManagerService inputManagerF = inputManager;
final TelephonyRegistry telephonyRegistryF = telephonyRegistry;
final MediaRouterService mediaRouterF = mediaRouter;
+ final AudioService audioServiceF = audioService;
// We now tell the activity manager it is okay to run third party
// code. It will call back into us once it has gotten to the state
@@ -1152,6 +1155,11 @@
} catch (Throwable e) {
reportWtf("making Recognition Service ready", e);
}
+ try {
+ if (audioServiceF != null) audioServiceF.systemReady();
+ } catch (Throwable e) {
+ reportWtf("Notifying AudioService running", e);
+ }
Watchdog.getInstance().start();
// It is now okay to let the various system services start their
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
index bb2bebf..d0f2a2d 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:trigger="state_checked" android:versionCode="1" >
+ android:versionCode="1" >
<size
android:height="48dp"
@@ -26,53 +26,11 @@
<group>
<path
- android:name="check"
- android:pathData="m20,200l100,90l180,-180l-35,-35l-145,145l-60,-60l-40,40z"
- android:fill="?android:attr/colorControlActivated" />
- </group>
- <group>
- <path
android:name="box1"
- android:pathData="m127,171l37,38l33,-31l-37,-40l-1,3l-2,0l-30,30z"
+ android:pathData="m20,200l100,90l180,-180l-35,-35l-145,145l-60,-60l-40,40z"
android:fill="?android:attr/colorControlActivated"
android:stroke="?android:attr/colorControlActivated"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
</group>
- <group>
- <path
- android:name="box2"
- android:pathData="m127,171l37,38l33,-31l-37,-40l-1,3l-2,0l-30,30z"
- android:rotation="46.757"
- android:pivotX="162"
- android:pivotY="173.5"
- android:fill="?android:attr/colorControlNormal"
- android:stroke="?android:attr/colorControlNormal"
- android:strokeWidth="3"
- android:strokeLineCap="round"
- android:strokeLineJoin="round" />
- </group>
- <group>
- <path
- android:name="box3"
- android:pathData="m187,147l-1,55l-49,-1l2,-53l48,0z"
- android:stroke="?android:attr/colorControlNormal"
- android:strokeWidth="10"
- android:strokeLineCap="round"
- android:strokeLineJoin="round" />
- </group>
- <group>
- <path
- android:name="box4"
- android:pathData="m248,74l0,164l-177,0l1,-165l173,-1l3,2z"
- android:stroke="?android:attr/colorControlNormal"
- android:strokeWidth="30"
- android:strokeLineCap="round"
- android:strokeLineJoin="round" />
- </group>
-
- <animation
- android:durations="300,100,0,300"
- android:sequence="check,box1,box2,box3,box4" />
-
</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable02.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable02.xml
index 49906d17..728624a 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable02.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable02.xml
@@ -23,14 +23,6 @@
<group>
<path
- android:name="arrow"
- android:pathData="M 100,225 L 100,115 L 130,115 L 70,15 L 10,115 L 40,115 L 40,225 z"
- android:fill="#ffffffff"
- android:stroke="#FF00FF00"
- android:strokeWidth="1"/>
- </group>
- <group>
- <path
android:name="house"
android:pathData="M 130,225 L 130,115 L 130,115 L 70,15 L 10,115 L 10,115 L 10,225 z"
android:fill="#ff440000"
@@ -42,5 +34,4 @@
android:trimPathStart=".1"
android:trimPathEnd=".9"/>
</group>
- <animation android:sequence="arrow,house"/>
</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable03.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable03.xml
index 137049d..1792683 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable03.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable03.xml
@@ -71,67 +71,4 @@
android:fill="#ff88ff"
/>
</group>
- <group>
- <path
- android:name="clip1"
- android:pathData="
- M 0, 0
- l 7.3, 0
- l 0, 12.25
- l -7.3, 0
- z"
- android:clipToPath="true"
- android:rotation="-30"
- android:pivotX="3.65"
- android:pivotY="6.125"
- />
- <path
- android:name="one"
- android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
- l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
- l -5.046875,0.0 0.0,-1.0Z"
- android:fill="#ff88ff"
- />
- <path
- android:name="clip2"
- android:pathData="
- M 0, 12.25
- l 7.3, 0
- l 0, 12.25
- l -7.3, 0
- z"
- android:clipToPath="true"
- android:rotation="-30"
- android:pivotX="3.65"
- android:pivotY="6.125"
- />
- <path
- android:name="two"
- android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
- q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
- q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
- q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
- q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
- q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
- q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
- q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
- q -0.78125024,0.8125 -2.2187502,2.265625Z"
- android:fill="#ff88ff"
- />
- </group>
-
-
- <animation
- android:sequence="one,one"
- android:durations="4000"/>
- <animation
- android:sequence="two,two"
- android:durations="4000"/>
- <animation
- android:sequence="clip1,clip1"
- android:durations="4000"/>
- <animation
- android:sequence="clip2,clip2"
- android:durations="4000"/>
-
</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml
index cffb73f..90694fb 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml
@@ -65,62 +65,4 @@
android:fill="#ff88ff"
/>
</group>
- <group>
- <path
- android:name="clip1"
- android:pathData="
- M 3.65, 6.125
- m -6, 0
- a 6,6 0 1,0 12,0
- a 6,6 0 1,0 -12,0z"
- android:clipToPath="true"
- android:fill="#332233"
- />
- <path
- android:name="one"
- android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
- l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
- l -5.046875,0.0 0.0,-1.0Z"
- android:fill="#ff88ff"
- />
- <path
- android:name="clip2"
- android:pathData="
- M 3.65, 6.125
- m -.001, 0
- a .001,.001 0 1,0 .002,0
- a .001,.001 0 1,0 -.002,0z"
- android:clipToPath="true"
- android:fill="#662233"
- />
- <path
- android:name="two"
- android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
- q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
- q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
- q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
- q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
- q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
- q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
- q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
- q -0.78125024,0.8125 -2.2187502,2.265625Z"
- android:fill="#ff88ff"
- />
- </group>
-
-
-
- <animation
- android:sequence="one,one"
- android:durations="4000"/>
- <animation
- android:sequence="two,two"
- android:durations="4000"/>
- <animation
- android:sequence="clip1,clip1"
- android:durations="4000"/>
- <animation
- android:sequence="clip2,clip2"
- android:durations="4000"/>
-
</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
index 0be6755..c6595fa 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
@@ -44,95 +44,4 @@
q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
q -0.78125024,0.8125 -2.2187502,2.265625Z" />
</group>
- <group>
- <path
- android:name="one"
- android:fill="#ffff00"
- android:fillOpacity="0"
- android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
-l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
-l -5.046875,0.0 0.0,-1.0Z" />
- <path
- android:name="two"
- android:fill="#ffff00"
- android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
- q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
- q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
- q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
- q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
- q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
- q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
- q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
- q -0.78125024,0.8125 -2.2187502,2.265625Z" />
- </group>
- <group>
- <path
- android:name="two"
- android:fill="#ffff00"
- android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
- q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
- q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
- q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
- q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
- q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
- q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
- q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
- q -0.78125024,0.8125 -2.2187502,2.265625Z" />
- <path
- android:name="three"
- android:fill="#ffff00"
- android:fillOpacity="0"
- android:pathData="M 5.103125,6.003125q 0.84375,0.1875 1.3125,0.765625 0.484375,0.5625 0.484375,1.40625
- q 0.0,1.296875 -0.890625,2.015625 -0.890625,0.703125 -2.53125,0.703125
- q -0.546875,0.0 -1.140625,-0.109375 -0.5781251,-0.109375 -1.1875001,-0.328125
- l 0.0,-1.140625q 0.484375,0.28125 1.0625001,0.4375 0.59375,0.140625 1.234375,0.140625
- q 1.109375,0.0 1.6875,-0.4375 0.59375,-0.4375 0.59375,-1.28125
- q 0.0,-0.765625 -0.546875,-1.203125 -0.546875,-0.4375 -1.5,-0.4375
- l -1.03125,0.0 0.0,-0.96875 1.078125,0.0q 0.859375,0.0 1.328125,-0.34375
- q 0.46875,-0.359375 0.46875,-1.015625 0.0,-0.671875 -0.484375,-1.03125
- q -0.46875,-0.359375 -1.359375,-0.359375 -0.5,0.0 -1.0625,0.109375
- q -0.546875,0.09375 -1.2187501,0.3125l 0.0,-1.046875q 0.6875001,-0.1875 1.2656251,-0.28125
- q 0.59375,-0.09375 1.109375,-0.09375 1.359375,0.0 2.140625,0.609375
- q 0.78125,0.609375 0.78125,1.65625 0.0,0.734375 -0.421875,1.234375
- q -0.40625,0.5 -1.171875,0.6875Z" />
- </group>
- <group>
- <path
- android:name="two"
- android:fill="#ffff00"
- android:fillOpacity="0"
- android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
- q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
- q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
- q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
- q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
- q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
- q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
- q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
- q -0.78125024,0.8125 -2.2187502,2.265625Z" />
- <path
- android:name="three"
- android:fill="#ffff00"
- android:pathData="M 5.103125,6.003125q 0.84375,0.1875 1.3125,0.765625 0.484375,0.5625 0.484375,1.40625
- q 0.0,1.296875 -0.890625,2.015625 -0.890625,0.703125 -2.53125,0.703125
- q -0.546875,0.0 -1.140625,-0.109375 -0.5781251,-0.109375 -1.1875001,-0.328125
- l 0.0,-1.140625q 0.484375,0.28125 1.0625001,0.4375 0.59375,0.140625 1.234375,0.140625
- q 1.109375,0.0 1.6875,-0.4375 0.59375,-0.4375 0.59375,-1.28125
- q 0.0,-0.765625 -0.546875,-1.203125 -0.546875,-0.4375 -1.5,-0.4375
- l -1.03125,0.0 0.0,-0.96875 1.078125,0.0q 0.859375,0.0 1.328125,-0.34375
- q 0.46875,-0.359375 0.46875,-1.015625 0.0,-0.671875 -0.484375,-1.03125
- q -0.46875,-0.359375 -1.359375,-0.359375 -0.5,0.0 -1.0625,0.109375
- q -0.546875,0.09375 -1.2187501,0.3125l 0.0,-1.046875q 0.6875001,-0.1875 1.2656251,-0.28125
- q 0.59375,-0.09375 1.109375,-0.09375 1.359375,0.0 2.140625,0.609375
- q 0.78125,0.609375 0.78125,1.65625 0.0,0.734375 -0.421875,1.234375
- q -0.40625,0.5 -1.171875,0.6875Z" />
- </group>
-
- <animation
- android:durations="2000,0,2000"
- android:sequence="one,one,three,three" />
- <animation
- android:durations="2000,0,2000"
- android:sequence="two,two,two,two" />
-
</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml
index 73ff5e2..850de28 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml
@@ -23,29 +23,6 @@
android:viewportHeight="700"/>
<group>
- </group>
- <path android:pathData="M 569.374 461.472L 569.374 160.658L 160.658 160.658L 160.658 461.472L 569.374 461.472z"
- android:name="path2451"
- android:stroke="#FF000000"
- android:strokeWidth="30.65500000000000"/>
- <path android:pathData="M 365.015 311.066"
- android:name="path2453"
- android:stroke="#FF000000"
- android:strokeWidth="30.655000000000001"/>
- <path android:pathData="M 164.46 164.49L 340.78 343.158C 353.849 356.328 377.63 356.172 390.423 343.278L 566.622 165.928"
- android:name="path2455"
- android:stroke="#FF000000"
- android:fill="#FF0000FF"
- android:strokeWidth="30.655000000000001"/>
- <path android:pathData="M 170.515 451.566L 305.61 313.46"
- android:name="path2457"
- android:stroke="#000000"
- android:strokeWidth="30.655000000000001"/>
- <path android:pathData="M 557.968 449.974L 426.515 315.375"
- android:name="path2459"
- android:stroke="#000000"
- android:strokeWidth="30.655000000000001"/>
- <group>
<path android:pathData="M 569.374 461.472L 569.374 160.658L 160.658 160.658L 160.658 461.472L 569.374 461.472z"
android:name="path2451"
android:stroke="#FF000000"
@@ -68,9 +45,4 @@
android:stroke="#000000"
android:strokeWidth="30.655000000000001"/>
</group>
-
- <animation android:sequence="path2451,path2451"
- android:durations="1000"/>
-
-
</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml
index 99d37ef..7c7e679 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml
@@ -19,14 +19,7 @@
<viewport android:viewportWidth="140"
android:viewportHeight="110"/>
- <group>
- <path
- android:name="menu"
- android:pathData="M 20,20 l 100,0 0,10 -100,0 z
- M 20,50 l 100,0 0,10 -100,0 z
- M 20,80 l 0,-10 100,0 0,10 z"
- android:fill="#ffffffff"/>
- </group>
+
<group>
<path
android:name="back"
@@ -34,12 +27,6 @@
M 27,50 l 97,0 0,10 -97,0 z
M 20,55 l 7.07,-7.07 35.3,35.3 -7.07,7.07 z"
android:fill="#ffffffff"
- android:rotation="180"
- android:pivotX="70"
- android:pivotY="55"
/>
</group>
- <animation android:sequence="menu,back"/>
-
-
</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable08.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable08.xml
index f8a03d7..59f7459 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable08.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable08.xml
@@ -31,18 +31,4 @@
android:strokeWidth="1"/>
</group>
- <group>
- <path
- android:name="pie2"
- android:pathData="M564.441,287A280.868,280.868 0 1,1 564.441,285L284.493,286.29Z"
- android:fill="#FFccaa00"
- android:stroke="#FF000000"
- android:strokeWidth="10"
- android:pivotX="90"
- android:pivotY="100"/>
- </group>
-
- <animation android:sequence="pie1,pie2"/>
-
-
</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml
index b3c91a88..2e379d6 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml
@@ -25,12 +25,6 @@
<group>
<path
- android:name="arrow"
- android:fill="#ffffffff"
- android:pathData="M 20,20 l 60,0 0,140 -60,0 z M 120,20 l 60,0 0,140 -60,0 z" />
- </group>
- <group>
- <path
android:name="house"
android:fill="#ffffffff"
android:pathData="M 100,20 l 0,0 0,140 -80,0 z M 100,20 l 0,0 80,140 -80,0 z"
@@ -39,6 +33,4 @@
android:rotation="90" />
</group>
- <animation android:sequence="arrow,house" />
-
</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml
index 7aca169..8484e9e 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml
@@ -21,8 +21,8 @@
android:width="64dp" />
<viewport
- android:viewportHeight="200"
- android:viewportWidth="200" />
+ android:viewportWidth="200"
+ android:viewportHeight="200"/>
<group>
<path
@@ -31,24 +31,6 @@
android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z" />
<path
android:name="bar2"
- android:fill="#FF555555"
- android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z" />
- <path
- android:name="bar1"
- android:fill="#FF555555"
- android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z" />
- <path
- android:name="bar0"
- android:fill="#FF555555"
- android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z" />
- </group>
- <group>
- <path
- android:name="bar3"
- android:fill="#FFFFFFFF"
- android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z" />
- <path
- android:name="bar2"
android:fill="#FFFFFFFF"
android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z" />
<path
@@ -60,54 +42,5 @@
android:fill="#FF555555"
android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z" />
</group>
- <group>
- <path
- android:name="bar3"
- android:fill="#FFFFFFFF"
- android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z" />
- <path
- android:name="bar2"
- android:fill="#FFFFFFFF"
- android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z" />
- <path
- android:name="bar1"
- android:fill="#FFFFFFFF"
- android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z" />
- <path
- android:name="bar0"
- android:fill="#FF555555"
- android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z" />
- </group>
- <group>
- <path
- android:name="bar3"
- android:fill="#FFFFFFFF"
- android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z" />
- <path
- android:name="bar2"
- android:fill="#FFFFFFFF"
- android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z" />
- <path
- android:name="bar1"
- android:fill="#FFFFFFFF"
- android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z" />
- <path
- android:name="bar0"
- android:fill="#FFFFFFFF"
- android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z" />
- </group>
-
- <animation
- android:durations="500,500,500"
- android:sequence="bar0,bar0,bar0,bar0" />
- <animation
- android:durations="500,500,500"
- android:sequence="bar1,bar1,bar1,bar1" />
- <animation
- android:durations="500,500,500"
- android:sequence="bar2,bar2,bar2,bar2" />
- <animation
- android:durations="500,500,500"
- android:sequence="bar3,bar3,bar3,bar3" />
</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml
index a4403c5..2b6c5d3 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml
@@ -36,25 +36,5 @@
android:fill="#FFFF0000"
android:pathData="M 30,18.031528 L 25.579581,23.421071 L 29.370621,26.765348 L 20.096792,37 L 21.156922,28.014053 L 17,24.902844 L 20.880632,18 L 30,18.031528 z" />
</group>
- <group>
- <path
- android:name="battery"
- android:fill="#ff8833"
- android:pathData="M 20.28125,2.0000002 C 17.352748,2.0000002 15,4.3527485 15,7.2812502 L 15,8.0000002 L 13.15625,8.0000002 C 9.7507553,8.0000002 7,10.750759 7,14.15625 L 7,39.84375 C 7,43.24924 9.7507558,46 13.15625,46 L 33.84375,46 C 37.249245,46 39.999999,43.24924 40,39.84375 L 40,14.15625 C 40,10.75076 37.249243,8.0000002 33.84375,8.0000002 L 32,8.0000002 L 32,7.2812502 C 32,4.3527485 29.647252,2.0000002 26.71875,2.0000002 L 20.28125,2.0000002 z"
- android:rotation="0"
- android:stroke="#3388ff"
- android:strokeWidth="1" />
- <path
- android:name="spark"
- android:fill="#FFFF0000"
- android:pathData="M 30,18.031528 L 25.579581,23.421071 L 29.370621,26.765348 L 20.096792,37 L 21.156922,28.014053 L 17,24.902844 L 20.880632,18 L 30,18.031528 z" />
- </group>
-
- <animation
- android:durations="2000"
- android:sequence="spark,spark" />
- <animation
- android:durations="2000"
- android:sequence="battery,battery" />
</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
index 207879d..681eb4f 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
@@ -40,48 +40,5 @@
android:pivotY="300"
android:rotation="0" />
</group>
- <group>
- <path
- android:name="v"
- android:pathData="M300,70 l 0,-70 70,70 -70,70z"
- android:pivotX="300"
- android:pivotY="300"
- android:rotation="360" />
- <path
- android:name="pie2"
- android:pathData="M300,70 a230,230 0 1,0 1,0 z"
- android:pivotX="300"
- android:pivotY="300"
- android:rotation="360"
- android:stroke="#FF00FF00"
- android:strokeLineCap="round"
- android:strokeWidth="70"
- android:trimPathEnd=".5"
- android:trimPathOffset="0"
- android:trimPathStart="0" />
- </group>
-
- <animation
- android:animate="easeInOut"
- android:durations="2000"
- android:repeatCount="-1"
- android:repeatStyle="forward"
- android:sequence="pie1,pie2"
- android:startOffset="500" />
- <animation
- android:animate="easeInOut"
- android:durations="2000"
- android:repeatCount="-1"
- android:repeatStyle="forward"
- android:sequence="v,v"
- android:startOffset="500" />
- <animation
- android:animate="easeInOut"
- android:durations="2800"
- android:limitTo="trimPathEnd"
- android:repeatCount="-1"
- android:repeatStyle="reverse"
- android:sequence="pie1,pie2"
- android:startOffset="500" />
</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml
index 4a2ed90..ef1b8e4 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml
@@ -40,40 +40,5 @@
android:stroke="#FF0000FF"
android:strokeWidth="5" />
</group>
- <group>
- <path
- android:name="pie2"
- android:fill="#ffff0000"
- android:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z"
- android:pivotX="300"
- android:pivotY="200"
- android:rotation="360"
- android:stroke="#FF00FF00"
- android:strokeWidth="10" />
- <path
- android:name="half"
- android:fill="#FFFFFF00"
- android:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z"
- android:pivotX="300"
- android:pivotY="200"
- android:rotation="-360"
- android:stroke="#FF0000FF"
- android:strokeWidth="5" />
- </group>
-
- <animation
- android:animate="easeInOut"
- android:durations="1000"
- android:repeatCount="2"
- android:repeatStyle="forward"
- android:sequence="pie1,pie2"
- android:startOffset="500" />
- <animation
- android:animate="easeInOut"
- android:durations="1000"
- android:repeatCount="5"
- android:repeatStyle="forward"
- android:sequence="half,half"
- android:startOffset="500" />
</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
index 6ebd56b..77bf723 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
@@ -25,17 +25,6 @@
<group>
<path
- android:name="pie1"
- android:pathData="M200,450 l 50,-25
- a25,25 -30 0,1 100,-50 l 50,-25
- a25,50 -30 0,1 100,-50 l 50,-25
- a25,75 -30 0,1 100,-50 l 50,-25
- a25,100 -30 0,1 100,-50 l 50,-25"
- android:stroke="#FF00FF00"
- android:strokeWidth="10" />
- </group>
- <group>
- <path
android:name="pie2"
android:pathData="M200,350 l 50,-25
a25,12 -30 0,1 100,-50 l 50,-25
@@ -49,6 +38,4 @@
android:strokeWidth="10" />
</group>
- <animation android:sequence="pie1,pie2" />
-
</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml
index 3c92d25..df5838c 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml
@@ -25,14 +25,6 @@
<group>
<path
- android:name="arrow"
- android:fill="#ffffffff"
- android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
- android:stroke="#FFFF0000"
- android:strokeWidth="1" />
- </group>
- <group>
- <path
android:name="house"
android:fill="#ff440000"
android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
@@ -43,6 +35,4 @@
android:strokeWidth="10" />
</group>
- <animation android:sequence="arrow,house" />
-
</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml
index 7e757a5..0bdcda5 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml
@@ -25,13 +25,6 @@
<group>
<path
- android:name="arrow"
- android:pathData="M 100,10 v 180 M 10,100 h 180"
- android:stroke="#FF00FF00"
- android:strokeWidth="1" />
- </group>
- <group>
- <path
android:name="house"
android:pathData="M 100,10 v 90 M 10,100 h 90"
android:pivotX="100"
@@ -41,6 +34,4 @@
android:strokeWidth="10" />
</group>
- <animation android:sequence="arrow,house" />
-
</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml
index 9427652..4453ae4 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml
@@ -23,14 +23,6 @@
<group>
<path
- android:name="arrow"
- android:pathData="M200,300 Q400,50 600,300 T1000,300"
- android:stroke="#FF00FF00"
- android:strokeWidth="1"/>
- </group>
-
- <group>
- <path
android:name="house"
android:pathData="M200,300 Q400,50 600,300 T1000,300"
android:stroke="#FFFF0000"
@@ -40,7 +32,4 @@
android:pivotY="300"/>
</group>
- <animation android:sequence="arrow,house"/>
-
-
</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml
index 69212f5..dfae9ac 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml
@@ -25,21 +25,13 @@
<group>
<path
- android:name="arrow"
- android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
- android:stroke="#FFFFFF00"
- android:strokeWidth="10" />
- </group>
- <group>
- <path
android:name="house"
android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
android:pivotX="250"
android:pivotY="200"
android:rotation="360"
+ android:stroke="#FFFFFF00"
android:strokeWidth="10" />
</group>
- <animation android:sequence="arrow,house" />
-
</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
index 2dca48d..a890fd6 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
@@ -25,13 +25,6 @@
<group>
<path
- android:name="arrow"
- android:pathData="M10,300 Q400,50 600,300 T1000,300"
- android:stroke="#FF00FFFF"
- android:strokeWidth="40" />
- </group>
- <group>
- <path
android:name="house"
android:pathData="M10,300 Q400,550 600,300 T1000,300"
android:pivotX="90"
@@ -40,6 +33,4 @@
android:strokeWidth="60" />
</group>
- <animation android:sequence="arrow,house" />
-
</vector>
\ No newline at end of file
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index ce8c8b8..85b81d9 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -506,6 +506,12 @@
* @hide
*/
public boolean isValid() {
+ if (SSID == null)
+ return false;
+
+ if (allowedKeyManagement == null)
+ return false;
+
if (allowedKeyManagement.cardinality() > 1) {
if (allowedKeyManagement.cardinality() != 2) {
return false;