diff options
206 files changed, 5113 insertions, 2682 deletions
diff --git a/Android.mk b/Android.mk index 99d73fa98f32..5e634c1a839f 100644 --- a/Android.mk +++ b/Android.mk @@ -76,8 +76,8 @@ LOCAL_SRC_FILES += \ 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 bc7bbcc99d9e..9910fdf4f143 100644 --- a/api/current.txt +++ b/api/current.txt @@ -250,7 +250,7 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { field public static final int dropDownWidth = 16843362; // 0x1010262 field public static final int duplicateParentState = 16842985; // 0x10100e9 field public static final int duration = 16843160; // 0x1010198 - field public static final int 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { field public static final int layout_x = 16843135; // 0x101017f field public static final int layout_y = 16843136; // 0x1010180 field public static final int left = 16843181; // 0x10101ad - field public static final int 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ -4438,6 +4432,7 @@ package android.app { field public static final java.lang.String CATEGORY_STATUS = "status"; field public static final java.lang.String CATEGORY_SYSTEM = "sys"; field public static final java.lang.String CATEGORY_TRANSPORT = "transport"; + field public static final int COLOR_DEFAULT = 0; // 0x0 field public static final android.os.Parcelable.Creator CREATOR; field public static final int DEFAULT_ALL = -1; // 0xffffffff field public static final int DEFAULT_LIGHTS = 4; // 0x4 @@ -4483,6 +4478,7 @@ package android.app { field public int audioStreamType; field public android.widget.RemoteViews bigContentView; field public java.lang.String category; + field public int color; field public android.app.PendingIntent contentIntent; field public android.widget.RemoteViews contentView; field public int defaults; @@ -4545,6 +4541,7 @@ package android.app { method public deprecated android.app.Notification getNotification(); method public android.app.Notification.Builder setAutoCancel(boolean); method public android.app.Notification.Builder setCategory(java.lang.String); + method public android.app.Notification.Builder setColor(int); method public android.app.Notification.Builder setContent(android.widget.RemoteViews); method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence); method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent); @@ -5027,6 +5024,7 @@ package android.app.admin { method public void clearUserRestriction(android.content.ComponentName, java.lang.String); method public void enableSystemApp(android.content.ComponentName, java.lang.String); method public int enableSystemApp(android.content.ComponentName, android.content.Intent); + method public java.lang.String[] getAccountTypesWithManagementDisabled(); method public java.util.List<android.content.ComponentName> getActiveAdmins(); method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String); method public boolean getCameraDisabled(android.content.ComponentName); @@ -5052,13 +5050,16 @@ package android.app.admin { 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); method public boolean resetPassword(java.lang.String, int); + method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean); 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); @@ -8048,6 +8049,7 @@ package android.content.pm { 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"; @@ -12868,6 +12870,7 @@ package android.inputmethodservice { 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); @@ -12917,6 +12920,7 @@ package android.inputmethodservice { 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); @@ -13579,6 +13583,7 @@ package android.media { 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 @@ -13591,6 +13596,8 @@ package android.media { 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 { @@ -17131,6 +17138,7 @@ package android.nfc.cardemulation { } 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); @@ -17138,6 +17146,8 @@ package android.nfc.cardemulation { 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"; @@ -20544,6 +20554,7 @@ package android.os { 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"; @@ -20557,9 +20568,11 @@ package android.os { 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"; } @@ -25711,6 +25724,636 @@ package android.speech.tts { } +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 { @@ -28870,6 +29513,46 @@ package android.util { 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); } @@ -32543,6 +33226,34 @@ package android.view.inputmethod { 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(); @@ -32751,6 +33462,7 @@ package android.view.inputmethod { 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); @@ -32773,6 +33485,7 @@ package android.view.inputmethod { 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); @@ -33022,7 +33735,6 @@ package android.webkit { 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 36f9f4b697ec..ef6fcb726a17 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -4807,6 +4807,7 @@ public class Activity extends ContextThemeWrapper 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 5d809d81263d..044727d12182 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -20,7 +20,6 @@ import android.os.BatteryStats; 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 @@ public class ActivityManager { 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 @@ public class ActivityManager { * * @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 b616c1e59827..d813dab50e0f 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 class AppOpsManager { 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 @@ public class AppOpsManager { OP_WAKE_LOCK, OP_COARSE_LOCATION, OP_COARSE_LOCATION, + OP_GET_USAGE_STATS, }; /** @@ -302,6 +306,7 @@ public class AppOpsManager { null, OPSTR_MONITOR_LOCATION, OPSTR_MONITOR_HIGH_POWER_LOCATION, + null, }; /** @@ -352,6 +357,7 @@ public class AppOpsManager { "WAKE_LOCK", "MONITOR_LOCATION", "MONITOR_HIGH_POWER_LOCATION", + "GET_USAGE_STATS" }; /** @@ -402,6 +408,7 @@ public class AppOpsManager { 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 @@ public class AppOpsManager { AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_IGNORED, // OP_GET_USAGE_STATS }; /** @@ -504,6 +512,7 @@ public class AppOpsManager { 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 5ed503077470..801182d62d75 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -678,6 +678,11 @@ class ContextImpl extends Context { 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/Notification.java b/core/java/android/app/Notification.java index 25a1493b3b6c..bba6caf8b05f 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -17,7 +17,7 @@ package android.app; import com.android.internal.R; -import com.android.internal.util.LegacyNotificationUtil; +import com.android.internal.util.NotificationColorUtil; import android.annotation.IntDef; import android.content.Context; @@ -28,6 +28,7 @@ import android.graphics.PorterDuff; import android.media.AudioManager; import android.net.Uri; import android.os.BadParcelableException; +import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -420,6 +421,21 @@ public class Notification implements Parcelable @Priority public int priority; + /** + * Accent color (an ARGB integer like the constants in {@link android.graphics.Color}) + * to be applied by the standard Style templates when presenting this notification. + * + * The current template design constructs a colorful header image by overlaying the + * {@link #icon} image (stenciled in white) atop a field of this color. Alpha components are + * ignored. + */ + public int color = COLOR_DEFAULT; + + /** + * Special value of {@link #color} telling the system not to decorate this notification with + * any special color but instead use default colors when presenting this notification. + */ + public static final int COLOR_DEFAULT = 0; // AKA Color.TRANSPARENT /** * Sphere of visibility of this notification, which affects how and when the SystemUI reveals @@ -877,6 +893,8 @@ public class Notification implements Parcelable if (parcel.readInt() != 0) { publicVersion = Notification.CREATOR.createFromParcel(parcel); } + + color = parcel.readInt(); } @Override @@ -968,6 +986,8 @@ public class Notification implements Parcelable this.publicVersion.cloneInto(that.publicVersion, heavy); } + that.color = this.color; + if (!heavy) { that.lightenPayload(); // will clean out extras } @@ -1110,6 +1130,8 @@ public class Notification implements Parcelable } else { parcel.writeInt(0); } + + parcel.writeInt(color); } /** @@ -1218,6 +1240,7 @@ public class Notification implements Parcelable sb.append(Integer.toHexString(this.defaults)); sb.append(" flags=0x"); sb.append(Integer.toHexString(this.flags)); + sb.append(String.format(" color=0x%08x", this.color)); sb.append(" category="); sb.append(this.category); if (actions != null) { sb.append(" "); @@ -1309,9 +1332,10 @@ public class Notification implements Parcelable private boolean mShowWhen = true; private int mVisibility = VISIBILITY_PRIVATE; private Notification mPublicVersion = null; - private boolean mQuantumTheme; - private final LegacyNotificationUtil mLegacyNotificationUtil; + private final NotificationColorUtil mColorUtil; private ArrayList<String> mPeople; + private boolean mPreQuantum; + private int mColor = COLOR_DEFAULT; /** * Constructs a new Builder with the defaults: @@ -1341,12 +1365,8 @@ public class Notification implements Parcelable mPriority = PRIORITY_DEFAULT; mPeople = new ArrayList<String>(); - // TODO: Decide on targetSdk from calling app whether to use quantum theme. - mQuantumTheme = true; - - // TODO: Decide on targetSdk from calling app whether to instantiate the processor at - // all. - mLegacyNotificationUtil = LegacyNotificationUtil.getInstance(); + mPreQuantum = context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.L; + mColorUtil = NotificationColorUtil.getInstance(); } /** @@ -1853,29 +1873,38 @@ public class Notification implements Parcelable } } + /** + * Sets {@link Notification#color}. + * + * @param argb The accent color to use + * + * @return The same Builder. + */ + public Builder setColor(int argb) { + mColor = argb; + return this; + } + private RemoteViews applyStandardTemplate(int resId, boolean fitIn1U) { RemoteViews contentView = new RemoteViews(mContext.getPackageName(), resId); boolean showLine3 = false; boolean showLine2 = false; int smallIconImageViewId = R.id.icon; - if (!mQuantumTheme && mPriority < PRIORITY_LOW) { - contentView.setInt(R.id.icon, - "setBackgroundResource", R.drawable.notification_template_icon_low_bg); - contentView.setInt(R.id.status_bar_latest_event_content, - "setBackgroundResource", R.drawable.notification_bg_low); + if (mPriority < PRIORITY_LOW) { + // TODO: Low priority presentation } if (mLargeIcon != null) { contentView.setImageViewBitmap(R.id.icon, mLargeIcon); - processLegacyLargeIcon(mLargeIcon, contentView); + processLargeIcon(mLargeIcon, contentView); smallIconImageViewId = R.id.right_icon; } if (mSmallIcon != 0) { contentView.setImageViewResource(smallIconImageViewId, mSmallIcon); contentView.setViewVisibility(smallIconImageViewId, View.VISIBLE); if (mLargeIcon != null) { - processLegacySmallIcon(mSmallIcon, smallIconImageViewId, contentView); + processSmallRightIcon(mSmallIcon, smallIconImageViewId, contentView); } else { - processLegacyLargeIcon(mSmallIcon, contentView); + processSmallIconAsLarge(mSmallIcon, contentView); } } else { @@ -2035,12 +2064,12 @@ public class Notification implements Parcelable * doesn't create quantum notifications by itself) app. */ private boolean isLegacy() { - return mLegacyNotificationUtil != null; + return mColorUtil != null; } private void processLegacyAction(Action action, RemoteViews button) { if (isLegacy()) { - if (mLegacyNotificationUtil.isGrayscale(mContext, action.icon)) { + if (mColorUtil.isGrayscale(mContext, action.icon)) { button.setTextViewCompoundDrawablesRelativeColorFilter(R.id.action0, 0, mContext.getResources().getColor( R.color.notification_action_legacy_color_filter), @@ -2051,45 +2080,68 @@ public class Notification implements Parcelable private CharSequence processLegacyText(CharSequence charSequence) { if (isLegacy()) { - return mLegacyNotificationUtil.invertCharSequenceColors(charSequence); + return mColorUtil.invertCharSequenceColors(charSequence); } else { return charSequence; } } - private void processLegacyLargeIcon(int largeIconId, RemoteViews contentView) { - if (isLegacy()) { - processLegacyLargeIcon( - mLegacyNotificationUtil.isGrayscale(mContext, largeIconId), - contentView); + /** + * Apply any necessary background to smallIcons being used in the largeIcon spot. + */ + private void processSmallIconAsLarge(int largeIconId, RemoteViews contentView) { + if (!isLegacy() || mColorUtil.isGrayscale(mContext, largeIconId)) { + applyLargeIconBackground(contentView); } } - private void processLegacyLargeIcon(Bitmap largeIcon, RemoteViews contentView) { - if (isLegacy()) { - processLegacyLargeIcon( - mLegacyNotificationUtil.isGrayscale(largeIcon), - contentView); + /** + * Apply any necessary background to a largeIcon if it's a fake smallIcon (that is, + * if it's grayscale). + */ + // TODO: also check bounds, transparency, that sort of thing. + private void processLargeIcon(Bitmap largeIcon, RemoteViews contentView) { + if (!isLegacy() || mColorUtil.isGrayscale(largeIcon)) { + applyLargeIconBackground(contentView); } } - private void processLegacyLargeIcon(boolean isGrayscale, RemoteViews contentView) { - if (isLegacy() && isGrayscale) { - contentView.setInt(R.id.icon, "setBackgroundResource", - R.drawable.notification_icon_legacy_bg_inset); - } + /** + * Add a colored circle behind the largeIcon slot. + */ + private void applyLargeIconBackground(RemoteViews contentView) { + contentView.setInt(R.id.icon, "setBackgroundResource", + R.drawable.notification_icon_legacy_bg_inset); + + contentView.setDrawableParameters( + R.id.icon, + true, + -1, + mColor, + PorterDuff.Mode.SRC_ATOP, + -1); } - private void processLegacySmallIcon(int smallIconDrawableId, int smallIconImageViewId, + /** + * Recolor small icons when used in the R.id.right_icon slot. + */ + private void processSmallRightIcon(int smallIconDrawableId, int smallIconImageViewId, RemoteViews contentView) { - if (isLegacy()) { - if (mLegacyNotificationUtil.isGrayscale(mContext, smallIconDrawableId)) { - contentView.setDrawableParameters(smallIconImageViewId, false, -1, - mContext.getResources().getColor( - R.color.notification_action_legacy_color_filter), - PorterDuff.Mode.MULTIPLY, -1); - } + if (!isLegacy() || mColorUtil.isGrayscale(mContext, smallIconDrawableId)) { + contentView.setDrawableParameters(smallIconImageViewId, false, -1, + mContext.getResources().getColor( + R.color.notification_action_legacy_color_filter), + PorterDuff.Mode.MULTIPLY, -1); + } + } + + private int resolveColor() { + if (mColor == COLOR_DEFAULT) { + mColor = mContext.getResources().getColor(R.color.notification_icon_bg_color); + } else { + mColor |= 0xFF000000; // no alpha for custom colors } + return mColor; } /** @@ -2102,6 +2154,9 @@ public class Notification implements Parcelable n.icon = mSmallIcon; n.iconLevel = mSmallIconLevel; n.number = mNumber; + + n.color = resolveColor(); + n.contentView = makeContentView(); n.contentIntent = mContentIntent; n.deleteIntent = mDeleteIntent; @@ -2207,45 +2262,31 @@ public class Notification implements Parcelable private int getBaseLayoutResource() { - return mQuantumTheme - ? R.layout.notification_template_quantum_base - : R.layout.notification_template_base; + return R.layout.notification_template_quantum_base; } private int getBigBaseLayoutResource() { - return mQuantumTheme - ? R.layout.notification_template_quantum_big_base - : R.layout.notification_template_big_base; + return R.layout.notification_template_quantum_big_base; } private int getBigPictureLayoutResource() { - return mQuantumTheme - ? R.layout.notification_template_quantum_big_picture - : R.layout.notification_template_big_picture; + return R.layout.notification_template_quantum_big_picture; } private int getBigTextLayoutResource() { - return mQuantumTheme - ? R.layout.notification_template_quantum_big_text - : R.layout.notification_template_big_text; + return R.layout.notification_template_quantum_big_text; } private int getInboxLayoutResource() { - return mQuantumTheme - ? R.layout.notification_template_quantum_inbox - : R.layout.notification_template_inbox; + return R.layout.notification_template_quantum_inbox; } private int getActionLayoutResource() { - return mQuantumTheme - ? R.layout.notification_quantum_action - : R.layout.notification_action; + return R.layout.notification_quantum_action; } private int getActionTombstoneLayoutResource() { - return mQuantumTheme - ? R.layout.notification_quantum_action_tombstone - : R.layout.notification_action_tombstone; + return R.layout.notification_quantum_action_tombstone; } } diff --git a/core/java/android/app/UsageStats.aidl b/core/java/android/app/UsageStats.aidl new file mode 100644 index 000000000000..7dee70a7861f --- /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 000000000000..0aeba59c3f9a --- /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 000000000000..fbf9c3bc92a2 --- /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 209c536593fe..58049fd11914 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 android.util.Log; 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 @@ public class DevicePolicyManager { } /** - * 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 @@ public class DevicePolicyManager { } /** - * 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 @@ public class DevicePolicyManager { /** * 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 @@ public class DevicePolicyManager { /** * 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 @@ public class DevicePolicyManager { /** * 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 @@ public class DevicePolicyManager { /** * 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 @@ public class DevicePolicyManager { /** * 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 @@ public class DevicePolicyManager { } /** - * 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 @@ public class DevicePolicyManager { /** * 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 @@ public class DevicePolicyManager { /** * 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 @@ public class DevicePolicyManager { * {@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 @@ public class DevicePolicyManager { } /** - * 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. */ @@ -2062,6 +2068,28 @@ public class DevicePolicyManager { } /** + * Called by a profile owner to disable account management for a specific type of account. + * + * <p>The calling device admin must be a profile owner. If it is not, a + * security exception will be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param accountType For which account management is disabled or enabled. + * @param disabled The boolean indicating that account management will be disabled (true) or + * enabled (false). + */ + public void setAccountManagementDisabled(ComponentName admin, String accountType, + boolean disabled) { + if (mService != null) { + try { + mService.setAccountManagementDisabled(admin, accountType, disabled); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** * Called by profile or device owner to re-enable system apps by intent that were disabled * by default when the managed profile was created. This should only be called from a profile * or device owner running within a managed profile. @@ -2081,4 +2109,73 @@ public class DevicePolicyManager { } return 0; } + + /** + * Gets the array of accounts for which account management is disabled by the profile owner. + * + * <p> Account management can be disabled/enabled by calling + * {@link #setAccountManagementDisabled}. + * + * @return a list of account types for which account management has been disabled. + * + * @see #setAccountManagementDisabled + */ + public String[] getAccountTypesWithManagementDisabled() { + if (mService != null) { + try { + return mService.getAccountTypesWithManagementDisabled(); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + + 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 b30f1b952b35..03ced0ffc2d9 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -126,4 +126,11 @@ interface IDevicePolicyManager { void enableSystemApp(in ComponentName admin, in String packageName); int enableSystemAppWithIntent(in ComponentName admin, in Intent intent); + + 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 042ee281d69c..a059e484dd48 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2683,6 +2683,16 @@ public abstract class Context { 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 52a169b2dbbe..eb2c11fe895f 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -936,13 +936,21 @@ public abstract class PackageManager { /** * 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 8437228257a0..ed223d1fd503 100644 --- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java @@ -36,6 +36,7 @@ import android.view.MotionEvent; 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 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub 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 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub 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 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub } @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 f6438b444cb5..4bccaf1d6f52 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -51,6 +51,7 @@ import android.view.WindowManager; 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 class InputMethodService extends AbstractInputMethodService { 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 @@ public class InputMethodService extends AbstractInputMethodService { } /** + * 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 ae9796b23ac3..521f4fd7b767 100644 --- a/core/java/android/nfc/INfcCardEmulation.aidl +++ b/core/java/android/nfc/INfcCardEmulation.aidl @@ -34,4 +34,6 @@ interface INfcCardEmulation 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 2820f4037e78..b04492247e59 100644 --- a/core/java/android/nfc/cardemulation/AidGroup.java +++ b/core/java/android/nfc/cardemulation/AidGroup.java @@ -12,10 +12,15 @@ import android.os.Parcelable; 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 @@ public final class AidGroup implements Parcelable { * 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 @@ public final class AidGroup implements Parcelable { 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 @@ public final class AidGroup implements Parcelable { } } - 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 94f35ed5a87f..f379ee8b7f0a 100644 --- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java +++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java @@ -290,6 +290,20 @@ public final class ApduServiceInfo implements Parcelable { 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 41f039cfc7ca..e24a22acbf3b 100644 --- a/core/java/android/nfc/cardemulation/CardEmulation.java +++ b/core/java/android/nfc/cardemulation/CardEmulation.java @@ -18,6 +18,7 @@ package android.nfc.cardemulation; 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.nfc.NfcAdapter; 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 @@ public final class CardEmulation { } /** + * 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 @@ public final class CardEmulation { 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 @@ public final class CardEmulation { * 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 @@ public final class CardEmulation { * 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 @@ public final class CardEmulation { } /** + * 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 e78ce339d120..8b7467fa1619 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -135,7 +135,7 @@ public abstract class BatteryStats implements Parcelable { /** * 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 899a9586863e..cd470997184b 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -36,6 +36,7 @@ interface IUserManager { 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/com/android/internal/os/PkgUsageStats.aidl b/core/java/android/os/ParcelableParcel.aidl index 83052717bf1f..61f730c1a75a 100644 --- a/core/java/com/android/internal/os/PkgUsageStats.aidl +++ b/core/java/android/os/ParcelableParcel.aidl @@ -1,20 +1,19 @@ -/* //device/java/android/android/content/Intent.aidl +/* +** Copyright 2014, The Android Open Source Project ** -** 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 ** -** 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 ** -** 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 +** 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; +package android.os; -parcelable PkgUsageStats; +parcelable ParcelableParcel; diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 84639ebc370a..312cdbefa348 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -234,6 +234,38 @@ public class UserManager { */ 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 @@ public class UserManager { } /** - * 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 @@ public class UserManager { } /** - * 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 @@ public class UserManager { } /** + * 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 @@ public class UserManager { 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 @@ public class UserManager { /** * 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 e4f73cb40b27..811751d18fef 100644 --- a/core/java/android/print/PrintManager.java +++ b/core/java/android/print/PrintManager.java @@ -167,7 +167,7 @@ public final class PrintManager { /** * Callback notifying that a print job state changed. - * + * * @param printJobId The print job id. */ public void onPrintJobStateChanged(PrintJobId printJobId); @@ -175,7 +175,7 @@ public final class PrintManager { /** * Creates a new instance. - * + * * @param context The current context in which to operate. * @param service The backing system service. * @hide @@ -207,13 +207,17 @@ public final class PrintManager { /** * 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 @@ public final class PrintManager { /** * 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 @@ public final class PrintManager { /** * 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 @@ public final class PrintManager { /** * 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 @@ public final class PrintManager { /** * 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 @@ public final class PrintManager { } 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 @@ public final class PrintManager { } 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 final class PrintManager { */ 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 @@ public final class PrintManager { /** * 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 @@ public final class PrintManager { /** * 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 @@ public final class PrintManager { * @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 e0ac60b85b47..1847b5558f29 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2823,7 +2823,6 @@ public final class Settings { 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 final class Settings { 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 final class Settings { */ 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 2549fde62634..49a0138734bb 100644 --- a/core/java/android/transition/Transition.java +++ b/core/java/android/transition/Transition.java @@ -351,18 +351,8 @@ public abstract class Transition implements Cloneable { } 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 @@ public abstract class Transition implements Cloneable { } 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 @@ public abstract class Transition implements Cloneable { } } // 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 f234baa01e4a..6c451ebd80cc 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -43,7 +43,6 @@ import android.text.TextUtils; 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 @@ class GLES20Canvas extends HardwareCanvas { 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 @@ class GLES20Canvas extends HardwareCanvas { 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 @@ class GLES20Canvas extends HardwareCanvas { } 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 05e202bf8a7c..2d1016a68233 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -1685,10 +1685,6 @@ public class KeyEvent extends InputEvent implements Parcelable { 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 1b04e4980588..a43dfe89cee1 100644 --- a/core/java/android/view/inputmethod/CorrectionInfo.java +++ b/core/java/android/view/inputmethod/CorrectionInfo.java @@ -88,16 +88,15 @@ public final class CorrectionInfo implements Parcelable { /** * 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 000000000000..2ee9edbd1b31 --- /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 000000000000..92455df900b1 --- /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 02278733d270..e1c6f522f101 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -49,6 +49,7 @@ import android.view.InputEventSender; 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 @@ public final class InputMethodManager { * 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 @@ public final class InputMethodManager { || mCurrentTextBoxAttribute == null || mCurMethod == null) { return; } - + if (mCursorSelStart != selStart || mCursorSelEnd != selEnd || mCursorCandStart != candidatesStart || mCursorCandEnd != candidatesEnd) { @@ -1556,6 +1558,31 @@ public final class InputMethodManager { } /** + * 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 63862999519d..74fbbc7e22ad 100644 --- a/core/java/android/view/inputmethod/InputMethodSession.java +++ b/core/java/android/view/inputmethod/InputMethodSession.java @@ -165,7 +165,7 @@ public interface InputMethodSession { 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 @@ public interface InputMethodSession { * {@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 000000000000..40cade74f864 --- /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 b0b5493ee547..a90aebd71716 100644 --- a/core/java/android/webkit/EventLogTags.logtags +++ b/core/java/android/webkit/EventLogTags.logtags @@ -8,3 +8,4 @@ option java_package android.webkit; # 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 3e334984ea9f..fa760b77cc37 100644 --- a/core/java/android/webkit/PermissionRequest.java +++ b/core/java/android/webkit/PermissionRequest.java @@ -28,6 +28,7 @@ import android.net.Uri; 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 e4ad354497e5..99a7886ed5f1 100644 --- a/core/java/android/widget/ShareActionProvider.java +++ b/core/java/android/widget/ShareActionProvider.java @@ -276,8 +276,13 @@ public class ShareActionProvider extends ActionProvider { * @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 @@ public class ShareActionProvider extends ActionProvider { 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 b91111d5e336..8f073deccde1 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -289,6 +289,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private Spannable.Factory mSpannableFactory = Spannable.Factory.getInstance(); private float mShadowRadius, mShadowDx, mShadowDy; + private int mShadowColor; + private boolean mPreDrawRegistered; @@ -2755,6 +2757,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mShadowRadius = radius; mShadowDx = dx; mShadowDy = dy; + mShadowColor = color; // Will change text clip region if (mEditor != null) mEditor.invalidateTextDisplayList(); @@ -2804,7 +2807,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @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 1eda373477bb..106ac0b2ef0a 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -33,6 +33,14 @@ public class ChooserActivity extends ResolverActivity { 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 @@ public class ChooserActivity extends ResolverActivity { 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 1ea74090a419..7e7f0e17c6d5 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.java b/core/java/com/android/internal/os/PkgUsageStats.java deleted file mode 100644 index 8c2c4052d20a..000000000000 --- 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/util/LegacyNotificationUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java index 0394bbcf9625..f38cbde4730b 100644 --- a/core/java/com/android/internal/util/LegacyNotificationUtil.java +++ b/core/java/com/android/internal/util/NotificationColorUtil.java @@ -24,6 +24,7 @@ import android.graphics.Color; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.VectorDrawable; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.style.TextAppearanceSpan; @@ -38,21 +39,21 @@ import java.util.WeakHashMap; * * @hide */ -public class LegacyNotificationUtil { +public class NotificationColorUtil { - private static final String TAG = "LegacyNotificationUtil"; + private static final String TAG = "NotificationColorUtil"; private static final Object sLock = new Object(); - private static LegacyNotificationUtil sInstance; + private static NotificationColorUtil sInstance; private final ImageUtils mImageUtils = new ImageUtils(); private final WeakHashMap<Bitmap, Pair<Boolean, Integer>> mGrayscaleBitmapCache = new WeakHashMap<Bitmap, Pair<Boolean, Integer>>(); - public static LegacyNotificationUtil getInstance() { + public static NotificationColorUtil getInstance() { synchronized (sLock) { if (sInstance == null) { - sInstance = new LegacyNotificationUtil(); + sInstance = new NotificationColorUtil(); } return sInstance; } @@ -107,6 +108,9 @@ public class LegacyNotificationUtil { AnimationDrawable ad = (AnimationDrawable) d; int count = ad.getNumberOfFrames(); return count > 0 && isGrayscale(ad.getFrame(0)); + } else if (d instanceof VectorDrawable) { + // We just assume you're doing the right thing if using vectors + return true; } else { return false; } diff --git a/core/java/com/android/internal/view/IInputMethodSession.aidl b/core/java/com/android/internal/view/IInputMethodSession.aidl index 90210ce9866c..367b713ed78f 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.os.Bundle; 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 @@ oneway interface IInputMethodSession { 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 674d084d4928..bcfa036ca2c9 100644 --- a/core/java/com/android/internal/widget/SwipeDismissLayout.java +++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java @@ -35,7 +35,7 @@ import android.widget.FrameLayout; 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 @@ public class SwipeDismissLayout extends FrameLayout { 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 @@ public class SwipeDismissLayout extends FrameLayout { 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 @@ public class SwipeDismissLayout extends FrameLayout { // 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 8bd2e4f9e9a3..51e2871867e2 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -241,8 +241,6 @@ LOCAL_SHARED_LIBRARIES += \ # <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 08a88d15974e..22c17dd2c20f 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 @@ public: 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 @@ static JNINativeMethod methods[] = { (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 da7527525eb5..463a0a86933f 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -526,12 +526,15 @@ jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const jbyte* da 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_short(JNIEnv *env, jobject thiz, // ---------------------------------------------------------------------------- +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 @@ static JNINativeMethod gMethods[] = { "(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 7b2f8296c354..fae6698569ef 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -79,7 +79,6 @@ using namespace uirenderer; #define RENDERER_LOGD(...) #endif -#define MODIFIER_SHADOW 1 #define MODIFIER_SHADER 2 // ---------------------------------------------------------------------------- @@ -617,7 +616,6 @@ static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz, 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_setupShader(JNIEnv* env, jobject clazz, } -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 @@ static JNINativeMethod gMethods[] = { { "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 0600522c7763..4b329ade5ae8 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/drawable/notification_icon_legacy_bg.xml b/core/res/res/drawable/notification_icon_legacy_bg.xml index 4ac67c3e4765..cc5755d5618c 100644 --- a/core/res/res/drawable/notification_icon_legacy_bg.xml +++ b/core/res/res/drawable/notification_icon_legacy_bg.xml @@ -18,5 +18,5 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid - android:color="@color/notification_icon_legacy_bg_color"/> + android:color="@color/notification_icon_bg_color"/> </shape> diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 4358dd3f9121..790567e6204c 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 dbc0d43179ad..66b4a90bbb0a 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 03dfb1262a7e..eb2540dbc308 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 ea9ffb392762..751327bdaab6 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 ecec09901ec2..f9b9fd2f6e76 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 93107cabc06c..be2ed2912c58 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 568e093fb3e0..33a5a8185fd3 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 8a0141a4ee45..c7c5a085f5d1 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 793e5bfc5903..347669220059 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 547ca27427aa..4a675386fd7a 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 172877f542f7..d9473ece245a 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/colors.xml b/core/res/res/values/colors.xml index 761170d854d2..7d3fb444c1da 100644 --- a/core/res/res/values/colors.xml +++ b/core/res/res/values/colors.xml @@ -123,7 +123,7 @@ <drawable name="notification_template_icon_bg">#3333B5E5</drawable> <drawable name="notification_template_icon_low_bg">#0cffffff</drawable> - <color name="notification_icon_legacy_bg_color">#ff4285F4</color> + <color name="notification_icon_bg_color">#ffa3a3a3</color> <color name="notification_action_legacy_color_filter">#ff555555</color> <!-- Keyguard colors --> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index d0cdefe147f5..4e584c065fcd 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/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index a8a4b513d730..2bf72e8adb21 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1664,6 +1664,7 @@ <java-symbol type="layout" name="notification_template_quantum_big_text" /> <java-symbol type="layout" name="notification_template_quantum_inbox" /> <java-symbol type="color" name="notification_action_legacy_color_filter" /> + <java-symbol type="color" name="notification_icon_bg_color" /> <java-symbol type="drawable" name="notification_icon_legacy_bg_inset" /> <java-symbol type="drawable" name="notification_quantum_bg_dim" /> <java-symbol type="drawable" name="notification_quantum_bg" /> diff --git a/core/tests/inputmethodtests/run_core_inputmethod_test.sh b/core/tests/inputmethodtests/run_core_inputmethod_test.sh index 9029ba5c3f39..e0f4f6d4303a 100755 --- a/core/tests/inputmethodtests/run_core_inputmethod_test.sh +++ b/core/tests/inputmethodtests/run_core_inputmethod_test.sh @@ -21,4 +21,4 @@ if [[ $rebuild == true ]]; then $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 000000000000..59a63144c954 --- /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 000000000000..fae7230ac6ca --- /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 4057736c2715..6143b4b6a61d 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 @@ is sensitive to delays or lag in sound input or output.</td> </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 1e1128e87360..457b3ea33bdd 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -55,27 +55,6 @@ public class Paint { /** * @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 @@ public class Paint { 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 @@ public class Paint { 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 @@ public class Paint { * 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 @@ public class Paint { 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 3f8c45c82e5a..0862cdd3b28b 100644 --- a/graphics/java/android/graphics/SurfaceTexture.java +++ b/graphics/java/android/graphics/SurfaceTexture.java @@ -18,6 +18,7 @@ package android.graphics; 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 @@ public class SurfaceTexture { * 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 @@ public class SurfaceTexture { * 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 61b1b85a50ee..99ab4dde5514 100644 --- a/graphics/java/android/graphics/drawable/ShapeDrawable.java +++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java @@ -237,7 +237,7 @@ public class ShapeDrawable extends Drawable { 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 77712b66f023..ff4ab98ae1d1 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.graphics.Region; 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.ArrayList; 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 @@ import java.util.HashSet; * <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 @@ import java.util.HashSet; * 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 @@ import java.util.HashSet; * <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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { @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 @@ public class VectorDrawable extends Drawable { @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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { } // 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 @@ public class VectorDrawable extends Drawable { } } - 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { } } - 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 @@ public class VectorDrawable extends Drawable { } } - 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 @@ public class VectorDrawable extends Drawable { } 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 @@ public class VectorDrawable extends Drawable { } /** - * 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 class VectorDrawable extends Drawable { } } - 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { 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 eb0cac8944df..2cadf09dc63a 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -6,6 +6,7 @@ include $(CLEAR_VARS) 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 @@ ifeq ($(USE_OPENGL_RENDERER),true) 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 3d58964b6ed8..45b6624029c0 100644 --- a/libs/hwui/DeferredDisplayList.cpp +++ b/libs/hwui/DeferredDisplayList.cpp @@ -190,7 +190,7 @@ public: // 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 ce92beb898ba..f1d70eb33862 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -183,6 +183,10 @@ public: 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 @@ public: 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 @@ private: 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 @@ public: 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 8afd106330a8..c2ce6ed073e9 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -410,16 +410,6 @@ void DisplayListRenderer::setupShader(SkiaShader* shader) { 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 25e78c1c9b6d..185179a9f577 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -102,9 +102,6 @@ public: 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 f06106b14ee7..22683865c7a6 100644 --- a/libs/hwui/Matrix.cpp +++ b/libs/hwui/Matrix.cpp @@ -482,8 +482,8 @@ void Matrix4::decomposeScale(float& sx, float& sy) const { 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 26cb05fe686e..e33a0013a929 100644 --- a/libs/hwui/Matrix.h +++ b/libs/hwui/Matrix.h @@ -209,7 +209,7 @@ public: 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 6de369c6007c..5a977c836d52 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 @@ void OpenGLRenderer::finish() { 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 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text, 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 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text, } 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 @@ status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count 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 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, f 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 @@ void OpenGLRenderer::setupShader(SkiaShader* shader) { } /////////////////////////////////////////////////////////////////////////////// -// 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 4de52ac1e39b..1d4694523905 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 @@ struct DrawModifiers { 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 @@ public: 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 @@ public: 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 92964a8ca624..f38d8b7d0ef6 100644 --- a/libs/hwui/Rect.h +++ b/libs/hwui/Rect.h @@ -175,6 +175,10 @@ public: bottom += dy; } + void inset(float delta) { + outset(-delta); + } + void outset(float delta) { left -= delta; top -= delta; @@ -230,8 +234,8 @@ public: 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 3209a531ace0..57db816f43e8 100644 --- a/libs/hwui/Renderer.h +++ b/libs/hwui/Renderer.h @@ -178,9 +178,6 @@ public: 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 d26ee3884433..6bfa2033f8fc 100644 --- a/libs/hwui/Snapshot.cpp +++ b/libs/hwui/Snapshot.cpp @@ -27,9 +27,15 @@ namespace uirenderer { // 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 @@ Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0), * 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 85d90d030b53..c020b40a31ee 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 @@ void Blur::generateGaussianWeights(float* weights, int32_t radius) { // 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 6c176e95e33c..79aff652ca4e 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 000000000000..9b298ca2011d --- /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 000000000000..890e3740ef9f --- /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 7deabe981727..8ba44dca2e2d 100644 --- a/libs/hwui/utils/MathUtils.h +++ b/libs/hwui/utils/MathUtils.h @@ -38,4 +38,4 @@ public: } /* 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 0c8a823d8792..724022b2411b 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -149,6 +149,7 @@ public class AudioService extends IAudioService.Stub { 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 @@ public class AudioService extends IAudioService.Stub { 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 @@ public class AudioService extends IAudioService.Stub { 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 class AudioService extends IAudioService.Stub { } + 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 @@ public class AudioService extends IAudioService.Stub { /** @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 @@ public class AudioService extends IAudioService.Stub { /** @see AudioManager#stopBluetoothSco() */ public void stopBluetoothSco(IBinder cb){ if (!checkAudioSettingsPermission("stopBluetoothSco()") || - !mBootCompleted) { + !mSystemReady) { return; } ScoClient client = getScoClient(cb, false); @@ -3277,7 +3314,7 @@ public class AudioService extends IAudioService.Stub { int status; synchronized (mSoundEffectsLock) { - if (!mBootCompleted) { + if (!mSystemReady) { Log.w(TAG, "onLoadSoundEffects() called before boot complete"); return false; } @@ -3700,6 +3737,10 @@ public class AudioService extends IAudioService.Stub { case MSG_BROADCAST_BT_CONNECTION_STATE: onBroadcastScoConnectionState(msg.arg1); break; + + case MSG_SYSTEM_READY: + onSystemReady(); + break; } } } @@ -4169,36 +4210,6 @@ public class AudioService extends IAudioService.Stub { 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 1899685712a3..dab6eed4c701 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -72,6 +72,7 @@ import com.android.internal.app.IAppOpsService; * * 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 class AudioTrack 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 @@ public class AudioTrack * @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 @@ public class AudioTrack * @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 @@ public class AudioTrack * @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 @@ public class AudioTrack 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 @@ public class AudioTrack * 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 @@ public class AudioTrack } 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 class AudioTrack 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 @@ public class AudioTrack * 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 @@ public class AudioTrack /** - * @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 @@ public class AudioTrack 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 @@ public class AudioTrack 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 ed98b9630af7..90fe6950335d 100644 --- a/media/jni/Android.mk +++ b/media/jni/Android.mk @@ -66,8 +66,6 @@ LOCAL_C_INCLUDES += \ 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 e4954e781bbd..7d9cfa1c49f0 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 3267c36c7ef3..372bde2a0afc 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 f9b022cc8795..c29da1895b98 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 d8a3114ded5a..8ec48c8144c3 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 9d1e0361ae6c..7aaaaf302f60 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 22a032a78fa2..1c06615ac87f 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 00ac7071f0f0..febcab67f6af 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 bfad5bc8e6ad..658ece049914 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 94ba5c772963..c7d2703908f6 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 df442ab65626..c7400513f914 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 451476c92eba..40ecc49a5afc 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 6dcffcf6936a..0e98ce042f98 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 91a334ae2e56..f4098b7c78ea 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 91a334ae2e56..f4098b7c78ea 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 2150cbe5100b..51198e6b0b21 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 3424166b4cfd..1b73e18e3a28 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 8dbf9af6d325..0f95c60566a6 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 b2ac99057476..f36d04bcdabd 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 af0df4d57d7e..4ae3851e1c37 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 f01c99a9e374..c55a5fc375a1 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 5efbd2f0ea7e..112191800e52 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 e6d38ef25c8c..f9e6aad550da 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 b777b8f4b587..435f7010ba05 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 10732fe69fcd..7685477ac6f8 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 f1c4869ecdb0..7a8ab101dd22 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 f0b07131b750..cdb081644386 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 6a576826d154..401dbce2c089 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 3e87b7645f03..08ffc542f408 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 1edb630b98d3..2caa069392f8 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 9d4344abc047..62e40d06eb47 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 bb2d3b94c148..35a6917ba861 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 83ffa9f65b23..d7cd13b048a7 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 9a3d48384ece..991fb66b7b1f 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 379cfcebb29f..87087b46de69 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 ca07095bbdfd..04571e7db974 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 45453019ea93..3e7b660ed0b0 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 587b84f6d762..af50786dd5db 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 001e733c1f9a..9fa68b9efe04 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 8a6e33bbed96..8cf16bf34f43 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 4862d1bcd3d4..e51341dadcaa 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 012283a5f3bf..11843b672b82 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 0978d1875487..162d7634d9bb 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 25f643f045f1..9f82651dca8e 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 5c9764aafcfe..75ba35b6490a 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 976a793fdfd2..6bdc6f4caf04 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 1224c3aa7785..12c90ecd2406 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 10011bce9ed3..48d7727306a3 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 0c6a939f0220..dba27a151379 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 d8bd1b1d5f5f..0d58ed35935d 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 d308b518c81a..b626f78c83d9 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 b7becac57010..1ea94429e738 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 7929a3054d11..6cb4a4874ab1 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 92473a4dd164..17e720e3747e 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 9837ff8fbab6..1bf033f55ab5 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 534f520f67c8..a5284aebde46 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 56fc89c03c4f..8df2449ebd46 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 442fdb713753..8643ca81fcb6 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 54a3b1eb4cd8..9d93094e7b71 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 fc74f538e71c..07b7841b6d60 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 dfe8838a143b..48a1aceb0724 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 93a75bc5e655..c0376f00ccd6 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 8d3a5652fadc..b6e6ee281393 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 43697415b067..6418930d2c73 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 8ab646d2f766..6608c5d1e2ce 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 3be6932da9bc..b74f6ac27e8d 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.AppWidgetHostView; 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.model.TaskStack; 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 @@ class RecentsAppWidgetHost extends AppWidgetHost { /* Activity */ public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks, - RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks{ + RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks { FrameLayout mContainerView; RecentsView mRecentsView; View mEmptyView; @@ -308,6 +310,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView 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 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView // 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 cb7e42ada7bc..463cf748842c 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 class RecentsConfiguration { 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 @@ public class RecentsConfiguration { 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 000000000000..4e620b644457 --- /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 c9038ee13837..c64ca5456762 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 @@ public class RecentsTaskLoader { TaskResourceLoadQueue mLoadQueue; TaskResourceLoader mLoader; + RecentsPackageMonitor mPackageMonitor; + int mMaxThumbnailCacheSize; int mMaxIconCacheSize; @@ -325,6 +327,7 @@ public class RecentsTaskLoader { // 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 @@ public class RecentsTaskLoader { 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 @@ public class RecentsTaskLoader { } /** 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 @@ public class RecentsTaskLoader { 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 b41555f288ca..0d3ee382da0b 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 @@ public class SystemServicesProxy { } /** 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 eb7b5c6483f4..a6d7e676b362 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 @@ package com.android.systemui.recents.views; 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 android.widget.FrameLayout; 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 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV 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 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV } 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 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV 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 cfacd1818541..55c38a9aa62e 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.AnimatorListenerAdapter; 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.BakedBezierInterpolator; 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 com.android.systemui.recents.model.TaskStack; 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 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } } + // 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 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal 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 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { 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 45c2fae22cb9..b03f389eb5b4 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 @@ public class TaskView extends FrameLayout implements View.OnClickListener, .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/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java index c81a3c83f42a..91df9ef4ad03 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java @@ -175,8 +175,10 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView private void makeInactive() { if (mActivated) { // Make sure that we clear the hotspot from the center. - mBackgroundDimmed.setHotspot(0, getWidth() / 2, getActualHeight() / 2); - mBackgroundDimmed.removeHotspot(0); + if (mBackgroundDimmed != null) { + mBackgroundDimmed.setHotspot(0, getWidth() / 2, getActualHeight() / 2); + mBackgroundDimmed.removeHotspot(0); + } mActivated = false; } if (mOnActivatedListener != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 3b536677fde7..898f06e2fe43 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -70,7 +70,7 @@ import android.widget.TextView; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.statusbar.StatusBarIconList; -import com.android.internal.util.LegacyNotificationUtil; +import com.android.internal.util.NotificationColorUtil; import com.android.systemui.R; import com.android.systemui.RecentsComponent; import com.android.systemui.SearchPanelView; @@ -143,7 +143,7 @@ public abstract class BaseStatusBar extends SystemUI implements // public mode, private notifications, etc private boolean mLockscreenPublicMode = false; private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray(); - private LegacyNotificationUtil mLegacyNotificationUtil = LegacyNotificationUtil.getInstance(); + private NotificationColorUtil mNotificationColorUtil = NotificationColorUtil.getInstance(); private UserManager mUserManager; @@ -852,7 +852,7 @@ public abstract class BaseStatusBar extends SystemUI implements Drawable iconDrawable = StatusBarIconView.getIcon(mContext, ic); icon.setImageDrawable(iconDrawable); - if (mLegacyNotificationUtil.isGrayscale(iconDrawable)) { + if (mNotificationColorUtil.isGrayscale(iconDrawable)) { icon.setBackgroundResource( com.android.internal.R.drawable.notification_icon_legacy_bg_inset); } @@ -1029,6 +1029,9 @@ public abstract class BaseStatusBar extends SystemUI implements } 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 e24ddd9f5af7..48c54fc7a85f 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 class StatusBarKeyguardViewManager { public void show(Bundle options) { mShowing = true; mStatusBarWindowManager.setKeyguardShowing(true); - showBouncerOrKeyguard(); - updateStates(); + reset(); } /** @@ -95,7 +94,9 @@ public class StatusBarKeyguardViewManager { } private void showBouncer() { - mBouncer.show(); + if (!mOccluded) { + mBouncer.show(); + } updateStates(); } @@ -103,8 +104,15 @@ public class StatusBarKeyguardViewManager { * 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 class StatusBarKeyguardViewManager { 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 a4c9df56ac78..c2061f326a88 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 @@ public class StatusBarWindowManager { | 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 c9526986515f..ca383aa411d5 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 @@ public class StackStateAnimator { 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 @@ public class StackStateAnimator { 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 @@ public class StackStateAnimator { } }); 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 @@ public class StackStateAnimator { @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 (previousAnimator != null && !isRunning()) { - onAnimationFinished(); + 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); + } } - 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 @@ public class StackStateAnimator { @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 @@ public class StackStateAnimator { mWasCancelled = false; } }); + long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator); animator.setDuration(newDuration); animator.addListener(getGlobalAnimationFinishedListener()); // remove the tag when the animation is finished @@ -241,31 +272,42 @@ public class StackStateAnimator { }); 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 @@ public class StackStateAnimator { @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 @@ public class StackStateAnimator { @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 @@ public class StackStateAnimator { @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 @@ public class StackStateAnimator { * 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 07933b4528c7..f1ddc073fa18 100644 --- a/rs/jni/Android.mk +++ b/rs/jni/Android.mk @@ -27,7 +27,6 @@ LOCAL_C_INCLUDES += \ 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 361911219e19..4a59a8f063bf 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.ServiceConnection; 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } // 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { & 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 class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { || 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 ea03eb7a33dc..dfffa8a46370 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3517,6 +3517,18 @@ public class ConnectivityService extends IConnectivityManager.Stub { 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 132ca007e7f2..ea9de1e83ccc 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; 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 @@ public class VibratorService extends IVibratorService.Stub 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 class VibratorService extends IVibratorService.Stub 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 @@ public class VibratorService extends IVibratorService.Stub 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 @@ public class VibratorService extends IVibratorService.Stub // 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 @@ public class VibratorService extends IVibratorService.Stub } 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 50cfe48f69c8..c32beda8b6a4 100644 --- a/services/core/java/com/android/server/WiredAccessoryManager.java +++ b/services/core/java/com/android/server/WiredAccessoryManager.java @@ -70,6 +70,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { 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 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { 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 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } } + @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 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { 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 a09b8d2f3afd..09e7e12140a7 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1850,6 +1850,12 @@ public final class ActivityManagerService extends ActivityManagerNative @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>>(); @@ -1885,7 +1891,6 @@ public final class ActivityManagerService extends ActivityManagerNative removeTaskByIdLocked(tasksToRemove.get(i), 0); } } - return true; } @Override @@ -9565,6 +9570,7 @@ public final class ActivityManagerService extends ActivityManagerNative } mAppOpsService.systemReady(); + mUsageStatsService.systemReady(); mSystemReady = true; } @@ -14386,6 +14392,7 @@ public final class ActivityManagerService extends ActivityManagerNative newConfig.seq = mConfigurationSeq; mConfiguration = newConfig; Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + newConfig); + mUsageStatsService.noteStartConfig(newConfig); final Configuration configCopy = new Configuration(mConfiguration); @@ -16523,7 +16530,7 @@ public final class ActivityManagerService extends ActivityManagerNative } if ((userInfo.flags&UserInfo.FLAG_INITIALIZED) == 0) { - if (userId != 0) { + if (userId != UserHandle.USER_OWNER) { Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); broadcastIntentLocked(null, null, intent, null, @@ -16552,6 +16559,8 @@ public final class ActivityManagerService extends ActivityManagerNative EventLogTags.writeAmSwitchUser(userId); getUserManagerLocked().userForeground(userId); sendUserSwitchBroadcastsLocked(oldUserId, userId); + } else { + mStackSupervisor.startBackgroundUserLocked(userId, uss); } if (needStart) { @@ -16727,7 +16736,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - void finishUserSwitch(UserStartedState uss) { + void finishUserBoot(UserStartedState uss) { synchronized (this) { if (uss.mState == UserStartedState.STATE_BOOTING && mStartedUsers.get(uss.mHandle.getIdentifier()) == uss) { @@ -16741,6 +16750,12 @@ public final class ActivityManagerService extends ActivityManagerNative android.Manifest.permission.RECEIVE_BOOT_COMPLETED, AppOpsManager.OP_NONE, true, false, MY_PID, Process.SYSTEM_UID, userId); } + } + } + + void finishUserSwitch(UserStartedState uss) { + synchronized (this) { + finishUserBoot(uss); startProfilesLocked(); diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index a95710bbc473..442da314bd60 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 @@ final class ActivityStack { } } - /** - * 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 @@ final class ActivityStack { 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 @@ final class ActivityStack { 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 @@ final class ActivityStack { // 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 @@ final class ActivityStack { // 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 @@ final class ActivityStack { } } } - 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 b93b1d9a5331..ce3d853d800a 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -193,6 +193,9 @@ public final class ActivityStackSupervisor implements DisplayListener { /** Used on user changes */ final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>(); + /** Used to queue up any background users being started */ + final ArrayList<UserStartedState> mStartingBackgroundUsers = new ArrayList<UserStartedState>(); + /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity * is being brought in front of us. */ boolean mUserLeaving = false; @@ -1999,9 +2002,20 @@ public final class ActivityStackSupervisor implements DisplayListener { if (booting) { mService.finishBooting(); - } else if (startingUsers != null) { - for (int i = 0; i < startingUsers.size(); i++) { - mService.finishUserSwitch(startingUsers.get(i)); + } else { + // Complete user switch + if (startingUsers != null) { + for (int i = 0; i < startingUsers.size(); i++) { + mService.finishUserSwitch(startingUsers.get(i)); + } + } + // Complete starting up of background users + if (mStartingBackgroundUsers.size() > 0) { + startingUsers = new ArrayList<UserStartedState>(mStartingBackgroundUsers); + mStartingBackgroundUsers.clear(); + for (int i = 0; i < startingUsers.size(); i++) { + mService.finishUserBoot(startingUsers.get(i)); + } } } @@ -2441,21 +2455,12 @@ public final class ActivityStackSupervisor implements DisplayListener { 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); } } } @@ -2507,6 +2512,15 @@ public final class ActivityStackSupervisor implements DisplayListener { return homeInFront; } + /** + * Add background users to send boot completed events to. + * @param userId The user being started in the background + * @param uss The state object for the user. + */ + public void startBackgroundUserLocked(int userId, UserStartedState uss) { + mStartingBackgroundUsers.add(uss); + } + final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) { int N = mStoppingActivities.size(); if (N <= 0) return null; diff --git a/services/core/java/com/android/server/am/UsageStatsService.java b/services/core/java/com/android/server/am/UsageStatsService.java index 42cf9004ed68..4a5a554b30a2 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 org.xmlpull.v1.XmlSerializer; 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.Calendar; 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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { } } - 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 @@ public final class UsageStatsService extends IUsageStats.Stub { } } - 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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { } } - 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 @@ public final class UsageStatsService extends IUsageStats.Stub { + 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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { if (!backupFile.exists()) { if (!mFile.renameTo(backupFile)) { Slog.w(TAG, "Failed to persist new stats"); + out.recycle(); return; } } else { @@ -562,14 +571,10 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { } } - 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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { @Override public void onPackageRemovedAllUsers(String packageName, int uid) { synchronized (mStatsLock) { - mLastResumeTimes.remove(packageName); + mStats.mPackages.remove(packageName); } } }; @@ -729,9 +723,10 @@ public final class UsageStatsService extends IUsageStats.Stub { // 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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { } @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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 @@ public final class UsageStatsService extends IUsageStats.Stub { } 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 @@ public final class UsageStatsService extends IUsageStats.Stub { } 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 @@ public final class UsageStatsService extends IUsageStats.Stub { } 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 @@ public final class UsageStatsService extends IUsageStats.Stub { 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 54cb0352a6c7..0f5805c857d6 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 @@ public class InputManagerService extends IInputManager.Stub 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 class InputManagerService extends IInputManager.Stub */ 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 ed60de47f8f2..46985874045d 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -471,6 +471,7 @@ public class NotificationManagerService extends SystemService { pw.println(prefix + String.format(" defaults=0x%08x flags=0x%08x", notification.defaults, notification.flags)); pw.println(prefix + " sound=" + notification.sound); + pw.println(prefix + String.format(" color=0x%08x", notification.color)); pw.println(prefix + " vibrate=" + Arrays.toString(notification.vibrate)); pw.println(prefix + String.format(" led=0x%08x onMs=%d offMs=%d", notification.ledARGB, notification.ledOnMS, notification.ledOffMS)); diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index 48e97378273a..bd28e048c0c5 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -239,8 +239,10 @@ public class LauncherAppsService extends ILauncherApps.Stub { private class MyPackageMonitor extends PackageMonitor { - /** Checks if user is a profile of or same as listeningUser. */ - private boolean isProfileOf(UserHandle user, UserHandle listeningUser, String debugMsg) { + /** Checks if user is a profile of or same as listeningUser. + * and the user is enabled. */ + private boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser, + String debugMsg) { if (user.getIdentifier() == listeningUser.getIdentifier()) { if (DEBUG) Log.d(TAG, "Delivering msg to same user " + debugMsg); return true; @@ -251,7 +253,8 @@ public class LauncherAppsService extends ILauncherApps.Stub { UserInfo listeningUserInfo = mUm.getUserInfo(listeningUser.getIdentifier()); if (userInfo == null || listeningUserInfo == null || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID - || userInfo.profileGroupId != listeningUserInfo.profileGroupId) { + || userInfo.profileGroupId != listeningUserInfo.profileGroupId + || !userInfo.isEnabled()) { if (DEBUG) { Log.d(TAG, "Not delivering msg from " + user + " to " + listeningUser + ":" + debugMsg); @@ -276,7 +279,7 @@ public class LauncherAppsService extends ILauncherApps.Stub { for (int i = 0; i < n; i++) { IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i); - if (!isProfileOf(user, listeningUser, "onPackageAdded")) continue; + if (!isEnabledProfileOf(user, listeningUser, "onPackageAdded")) continue; try { listener.onPackageAdded(user, packageName); } catch (RemoteException re) { @@ -295,7 +298,7 @@ public class LauncherAppsService extends ILauncherApps.Stub { for (int i = 0; i < n; i++) { IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i); - if (!isProfileOf(user, listeningUser, "onPackageRemoved")) continue; + if (!isEnabledProfileOf(user, listeningUser, "onPackageRemoved")) continue; try { listener.onPackageRemoved(user, packageName); } catch (RemoteException re) { @@ -314,7 +317,7 @@ public class LauncherAppsService extends ILauncherApps.Stub { for (int i = 0; i < n; i++) { IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i); - if (!isProfileOf(user, listeningUser, "onPackageModified")) continue; + if (!isEnabledProfileOf(user, listeningUser, "onPackageModified")) continue; try { listener.onPackageChanged(user, packageName); } catch (RemoteException re) { @@ -333,7 +336,7 @@ public class LauncherAppsService extends ILauncherApps.Stub { for (int i = 0; i < n; i++) { IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i); - if (!isProfileOf(user, listeningUser, "onPackagesAvailable")) continue; + if (!isEnabledProfileOf(user, listeningUser, "onPackagesAvailable")) continue; try { listener.onPackagesAvailable(user, packages, isReplacing()); } catch (RemoteException re) { @@ -352,7 +355,7 @@ public class LauncherAppsService extends ILauncherApps.Stub { for (int i = 0; i < n; i++) { IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i); - if (!isProfileOf(user, listeningUser, "onPackagesUnavailable")) continue; + if (!isEnabledProfileOf(user, listeningUser, "onPackagesUnavailable")) continue; try { listener.onPackagesUnavailable(user, packages, isReplacing()); } catch (RemoteException re) { diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 4f5326f7ede4..60212bfa5ab4 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 @@ public class UserManagerService extends IUserManager.Stub { 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 @@ public class UserManagerService extends IUserManager.Stub { 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 @@ public class UserManagerService extends IUserManager.Stub { 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 @@ public class UserManagerService extends IUserManager.Stub { } } - 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 @@ public class UserManagerService extends IUserManager.Stub { 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 @@ public class UserManagerService extends IUserManager.Stub { 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 90392369b856..99ec242902ce 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 @@ public class AppTransition implements Dump { /** 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 @@ public class AppTransition implements Dump { private final int mConfigShortAnimTime; private final Interpolator mDecelerateInterpolator; private final Interpolator mThumbnailFadeoutInterpolator; + private final Interpolator mThumbnailCubicInterpolator; private int mCurrentUserId = 0; @@ -170,6 +172,8 @@ public class AppTransition implements Dump { 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 @@ public class AppTransition implements Dump { /** * 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 @@ public class AppTransition implements Dump { 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 @@ public class AppTransition implements Dump { 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 dcca8377cba3..1980d1eb546a 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -97,9 +97,11 @@ import java.security.cert.CertificateFactory; 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; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -112,6 +114,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; @@ -126,6 +130,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final boolean DBG = false; final Context mContext; + final UserManager mUserManager; final PowerManager.WakeLock mWakeLock; IPowerManager mIPowerManager; @@ -181,6 +186,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; } @@ -202,7 +210,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + action + " for user " + userHandle); mHandler.post(new Runnable() { public void run() { - handlePasswordExpirationNotification(getUserData(userHandle)); + handlePasswordExpirationNotification(userHandle); } }); } @@ -232,6 +240,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { static class ActiveAdmin { private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features"; private static final String TAG_DISABLE_CAMERA = "disable-camera"; + private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management"; + private static final String TAG_ACCOUNT_TYPE = "account-type"; private static final String TAG_ENCRYPTION_REQUESTED = "encryption-requested"; private static final String TAG_PASSWORD_EXPIRATION_DATE = "password-expiration-date"; private static final String TAG_PASSWORD_EXPIRATION_TIMEOUT = "password-expiration-timeout"; @@ -297,6 +307,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { boolean encryptionRequested = false; boolean disableCamera = false; + Set<String> accountTypesWithManagementDisabled = new HashSet<String>(); // TODO: review implementation decisions with frameworks team boolean specifiesGlobalProxy = false; @@ -413,6 +424,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.attribute(null, ATTR_VALUE, Integer.toString(disabledKeyguardFeatures)); out.endTag(null, TAG_DISABLE_KEYGUARD_FEATURES); } + if (!accountTypesWithManagementDisabled.isEmpty()) { + out.startTag(null, TAG_DISABLE_ACCOUNT_MANAGEMENT); + for (String ac : accountTypesWithManagementDisabled) { + out.startTag(null, TAG_ACCOUNT_TYPE); + out.attribute(null, ATTR_VALUE, ac); + out.endTag(null, TAG_ACCOUNT_TYPE); + } + out.endTag(null, TAG_DISABLE_ACCOUNT_MANAGEMENT); + } } void readFromXml(XmlPullParser parser) @@ -484,6 +504,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } else if (TAG_DISABLE_KEYGUARD_FEATURES.equals(tag)) { disabledKeyguardFeatures = Integer.parseInt( parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_DISABLE_ACCOUNT_MANAGEMENT.equals(tag)) { + int outerDepthDAM = parser.getDepth(); + int typeDAM; + while ((typeDAM=parser.next()) != XmlPullParser.END_DOCUMENT + && (typeDAM != XmlPullParser.END_TAG + || parser.getDepth() > outerDepthDAM)) { + if (typeDAM == XmlPullParser.END_TAG || typeDAM == XmlPullParser.TEXT) { + continue; + } + String tagDAM = parser.getName(); + if (TAG_ACCOUNT_TYPE.equals(tagDAM)) { + accountTypesWithManagementDisabled.add( + parser.getAttributeValue(null, ATTR_VALUE)); + } else { + Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM); + } + } } else { Slog.w(LOG_TAG, "Unknown admin tag: " + tag); } @@ -575,6 +612,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { */ 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)) @@ -782,6 +820,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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()); @@ -796,12 +837,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + /** + * 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); } @@ -809,6 +853,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + /** + * 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) { @@ -925,6 +982,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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(); @@ -974,6 +1038,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } 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) { @@ -1026,6 +1091,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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); @@ -1141,23 +1211,29 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - 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)); } } @@ -1167,8 +1243,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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()); } @@ -1207,8 +1282,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // 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()); } @@ -1385,18 +1459,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; @@ -1427,7 +1505,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } enforceCrossUserPermission(userHandle); synchronized (this) { - DevicePolicyData policy = getUserData(userHandle); int length = 0; if (who != null) { @@ -1435,11 +1512,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; @@ -1470,7 +1552,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } enforceCrossUserPermission(userHandle); synchronized (this) { - DevicePolicyData policy = getUserData(userHandle); int length = 0; if (who != null) { @@ -1478,11 +1559,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; @@ -1528,19 +1614,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } 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; @@ -1552,19 +1642,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * 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; @@ -1611,12 +1705,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; @@ -1651,12 +1749,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; @@ -1694,12 +1796,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; @@ -1737,12 +1843,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; @@ -1780,12 +1890,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; @@ -1823,12 +1937,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; @@ -1840,8 +1958,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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, @@ -1863,13 +1989,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } 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; } } @@ -1879,6 +2008,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } 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, @@ -1898,7 +2030,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } enforceCrossUserPermission(userHandle); synchronized (this) { - DevicePolicyData policy = getUserData(userHandle); int count = 0; if (who != null) { @@ -1906,14 +2037,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; @@ -1925,9 +2061,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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); @@ -2105,15 +2243,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; @@ -2271,7 +2413,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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 @@ -2319,6 +2461,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return; } enforceCrossUserPermission(userHandle); + enforceNotManagedProfile(userHandle, "set the active password"); + mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); DevicePolicyData p = getUserData(userHandle); @@ -2347,7 +2491,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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); @@ -2357,26 +2502,31 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } /** - * 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); @@ -2391,7 +2541,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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 { @@ -2414,7 +2565,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { policy.mPasswordOwner = -1; saveSettingsLocked(userHandle); if (mHasFeature) { - sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED, + sendAdminCommandToSelfAndProfilesLocked( + DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle); } } finally { @@ -2443,7 +2595,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // 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 @@ -2472,8 +2624,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // 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; } } @@ -2858,8 +3013,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } 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); @@ -2905,10 +3059,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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 | @@ -2972,6 +3125,30 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + 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(); @@ -3075,10 +3252,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } 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); } @@ -3142,10 +3318,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } 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); } @@ -3162,10 +3337,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } 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); } @@ -3178,7 +3352,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (who == null) { throw new NullPointerException("ComponentName is null"); } - getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); int userId = UserHandle.getCallingUserId(); @@ -3277,4 +3450,112 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0, userId); return (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0; } + + @Override + public void setAccountManagementDisabled(ComponentName who, String accountType, + boolean disabled) { + if (!mHasFeature) { + return; + } + synchronized (this) { + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + ActiveAdmin ap = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + if (disabled) { + ap.accountTypesWithManagementDisabled.add(accountType); + } else { + ap.accountTypesWithManagementDisabled.remove(accountType); + } + saveSettingsLocked(UserHandle.getCallingUserId()); + } + } + + @Override + public String[] getAccountTypesWithManagementDisabled() { + if (!mHasFeature) { + return null; + } + synchronized (this) { + DevicePolicyData policy = getUserData(UserHandle.getCallingUserId()); + final int N = policy.mAdminList.size(); + HashSet<String> resultSet = new HashSet<String>(); + for (int i = 0; i < N; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); + resultSet.addAll(admin.accountTypesWithManagementDisabled); + } + 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 716823cf80a2..22e2a6e7c48a 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -334,6 +334,7 @@ public final class SystemServer { InputManagerService inputManager = null; TelephonyRegistry telephonyRegistry = null; ConsumerIrService consumerIr = null; + AudioService audioService = null; boolean onlyCore = false; boolean firstBoot = false; @@ -769,7 +770,8 @@ public final class SystemServer { 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 @@ public final class SystemServer { 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 @@ public final class SystemServer { } 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 bb2bebf80833..d0f2a2db366a 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 49906d17ebb7..728624a149ac 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 137049df2476..179268357815 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 cffb73f36b89..90694fbbc123 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 0be67558856d..c6595facbe66 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 73ff5e2e9837..850de2896500 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 99d37efe338f..7c7e679a3d1e 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 f8a03d761714..59f745942dc7 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 b3c91a88bced..2e379d675b09 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 7aca16960f7e..8484e9e2f107 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 a4403c5a9c50..2b6c5d31b32a 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 207879d6ab35..681eb4faf099 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 4a2ed90c6f5f..ef1b8e4cba33 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 6ebd56b41bd8..77bf7232c9af 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 3c92d25cc0b7..df5838c53e01 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 7e757a5f142c..0bdcda564603 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 9427652a1950..4453ae4b3569 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 69212f5dc01d..dfae9acb122d 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 2dca48d9c87d..a890fd6a8874 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 ce8c8b84faf4..85b81d969362 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -506,6 +506,12 @@ public class WifiConfiguration implements Parcelable { * @hide */ public boolean isValid() { + if (SSID == null) + return false; + + if (allowedKeyManagement == null) + return false; + if (allowedKeyManagement.cardinality() > 1) { if (allowedKeyManagement.cardinality() != 2) { return false; |